1. 程式人生 > >從什麼都不懂開始(三) 實踐帶你飛之Branch操作

從什麼都不懂開始(三) 實踐帶你飛之Branch操作

本篇將介紹一下Git中經常需要操作到的東西,以及專案中運用到的場景,會稍微帶一點基礎知識,筆者覺得阮一峰老師的Git入門講的非常到位了,我就不班門弄斧了,就講一下專案中遇到的一些情況。若是Git大牛就可以點選返回或者關閉啦~
此文多圖預警~用流量的童鞋注意哦。

Repository介紹

在版本管理中,Repository翻譯成中文就是倉庫的意思,每個提交到本地,或者push到遠端伺服器的Project,被Git以資料結構的形式儲存,而這個資料結構被稱之為Repository即倉庫。

對於我們來說,在Repository中,我們看的見的顯示資訊就是程式碼,而其他的比如分支資訊、Commit資訊、Status這些狀態則通過命令列去檢視。

Branch介紹

當我們多個人合作開發的時候,為了方便管理程式碼,會每個組開一個Branch,而master稱為主分支——主幹,這些Branch則稱為分支。

BranchAndMaster

檢視當前分支

在命令列輸入git branch就可以看到當前分支為master :
檢視當前分支

輸入git branch -a 可以檢視本地和遠端所有分支
檢視本地和遠端所有分支

切換分支

初始化Git後,當前預設在master分支,這個時候如果你想新建一個分支,可以執行 git branch [branchName] 後面的[branchName]是指你的分支名。這樣就能把master當前的commit資訊’拎’出來,成為了一個新的分支。

新建分支

執行完branch命令後,你會發現你還是在原來的分支上,在master前有一個*號表示當前分支是master,這個時候執行以下 git checkout [branchName]
切換當前分支到testBranch
其實呢,你可以執行
git checkout -b [branchName] [fromBranchName] 生成新的Branch,後面這個[fromBranchName] 就是你想要從哪個分支生成新的分支,不寫則是當前分支。

從當前分支檢出新分支

從master分支檢出新分支

HEAD資訊

為什麼要在這裡講HEAD呢,那HEAD又是什麼呢,其實HEAD可以理解成一個指標,每次都是指向當前Branch的最後一次資訊(可以是Commit或者Pull之類的),通過移動HEAD來達到切換分支的作用。
如果當前分支在master,那麼HEAD資訊如下:
HEAD_MASTER

真實測試效果:

HEAD_IN_MASTER
在checkout到BranchC的時候變成了如下圖所示:

HEAD_BRANCH

真實測試效果:

HEAD_IN_BRANCH

合併分支

當你的專案上線後,發現有個bug,這個時候需要在master分支上checkout -b 一個新的分支用來修bug,那麼這個bug分支上的程式碼,最後怎麼給’整’到master上去呢。很簡單先切回master分支,然後git merge bugBranch 就好了。

衝突

當你merge的時候出現了

$ git merge myBranch
Auto-merging AndroidManifest.xml
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

切換到bug分支
merge

這個時候會提示你有程式碼衝突,那麼你需要執行git status,檢視當前檔案哪些需要解決衝突。解決完再提交就好了。筆者很喜歡用AndroidStudio自帶的git進行合併等操作,可以直接在Compare檢視上解決衝突,非常方便。
發現衝突

衝突檔案

這個時候回發現 <<<<<<<<<< HEAD======== 是當前所在分支的內容,下面從 =======>>>>>>>> fixBug 是合併過來的分支,解決完,再執行git add . 然後就可以提交啦。

接下來為大家看一下編譯器的merge:

選擇merge

選擇分支:

選擇分支

衝突提示:

衝突提示

衝突比較 :

合併操作

rebase

rebase和merge的功能其實是一樣的,都是合併程式碼,只是對於修改資訊的節點會發生變化,rebase和merge最大的區別就是在最後的程式碼樹上,有興趣的同學可以用SourceTree看看,或者直接在命令列輸入gitk。

當前工作狀態,箭頭表示上一次資訊:
當前狀態

執行merge後:
merge

執行rebase後
rebase

之所以會有5-1,6-1就是和原來的commit是不同的,算是一次新的commit了。

簡而言之就是rebase的程式碼會比merge的乾淨許多。rebase會保留你合併的順序,而merge則會按照你的修改時間排序。筆者有點強迫症,會使用rebase(搞基),另外一些圖方便的人喜歡merge(合體)。

另外值得注意的是,在rebase前,千萬別push,不然等rebase完畢後,因為tree發生了變化,會提示push reject,意味著你需要 git push --f才能提交了,這是有風險的!!!注意安全!!!

比如branch要reabse onto master,那麼會比較兩個分支的最近的共同節點,再根據master提交的節點生成一系列不同的檔案,最後在branch上針對每個提交將之前不同的檔案去合併,並且生成新的commit節點,這時rebase完畢後branch的tree已經和rebase前的branch tree完全不一樣了,所以在rebase前你push過後,rebase後再push會提示不是同一個tree而reject(拒絕)提交。

下面是AndroidStudio上的rebase操作:
rebase選擇

想要從哪個分支rebase到當前分支,就選擇哪個Rebase on

選擇分支

stash

當你想切換分支時,又不想提交當前程式碼,那就需要stash啦,簡單的意思就是講你當前的修改資訊全部暫存起來,放進一個stack棧中,這個時候你就可以checkout到別的分支啦。下次再回來的時候
git stash pop就好了。

這個時候Leader轉頭對我說:XXX模組程式碼我提交了,你拉一下程式碼,我改了你可能要用到的東西。
這個時候我對著一螢幕的藍色提示,心想:不能commit把,都沒測試過。這個時候就用到stash這個神器了。

沒有提交檔案,本地修改過的檔案會顯示藍色:
藍色

專案裡有幾個檔案都沒有提交,只能選擇專案根目錄,右擊,選擇stash:

stash

會彈出一個stash的彈出框,會顯示當前分支,填入message:
stash彈出框

點選createStash後,建立一個當前的stash,可以點選剛剛的StashChanges下面的UnstashChanges檢視當前的stash列表:

檢視stashInAs

或者在命令列輸入git stash list 檢視當前的stash棧:
檢視stash

結果

好啦,當前的工作全部都暫存起來了!要把剛剛Leader放到master的程式碼都合併過來啦!我選擇的當然是rebase啦。在這之前必須得把伺服器的master程式碼pull到本地是不是,先切換到master,然後還是選擇編譯器的git,在剛剛stash介面下面有個pull。點選pull彈出一個介面,選擇master分支:

pull

點選pull就能拉下程式碼啦,如果有衝突也能借助編譯器的compare進行合併啦。

pull完程式碼後,要reabse啦:

rebase

按照步驟來,1、點選當前分支,選擇要rebase的目標分支,點選後選擇Rebase onto就可以執行rebase啦,rebase過程中發現出現了一個衝突:

衝突

和前面的merge一樣,選擇在這裡解決衝突:

解決衝突
這個時候master的程式碼就過來啦,然後再把之前修改的程式碼拿出來繼續工作:

pop

pop完後可以繼續快樂的工作啦:

pop完畢

在這裡說明一下紅色的檔案表示沒有add,綠色檔案表示add過了但是沒有commit,藍色檔案表示修改過,和遠端的分支程式碼不一樣,綠色和藍色的檔案執行stash會被暫存,而紅色的不會。

拓展

如果對Git原理有興趣的同學,可以自己再去深入研究一下Git,很多東西雖然平時用不到,但是又很有深度。大家按興趣就好啦

總結

一邊寫部落格,一邊翻閱資料,自己也又溫習一遍,接下來打算繼續深入下去,下一篇將會講幾個指令的原理,以及git物件之類的。最近比較忙,需要用點心去學習,也會把自己遇到的場景儘量告訴大家,讓大家能接觸到更多的實際場景,努力把這個系列寫的更乾貨一些!

其實AndroidStudio能覆蓋大多數的使用場景了,下一篇將會說一些revert、reset,當發生錯誤提交時,怎麼回滾程式碼。

最近大帥的開了個QQ實踐群(568863373),歡迎大家一起討論,也可以關注我們的公眾號:魔都三帥

公眾號