上一篇傳送門:熟練使用git 分支管理
在Git中,git merge
和git rebase
都是用來將一個分支的修改併入另一個分支,只不過方式不同。
在日常工作中基本都會有一個工作主分支,一般我們會新建一個新的分支開始我們的工作,以免影響主分支。我們假設以下的情景來說明程式碼合併。
小李需要開發FeatureA,因此他在專案主分支的基礎上新建了一個FeatureA的分支開始了他的工作,在他工作的同時,同事修復了兩個bug,並且都合入了主分支,於是程式碼分支變成 了下面這種情況:
這時候小李想基於修復好bug的版本繼續之前的開發,那麼就需要將自己的程式碼和已經分叉的主分支進行合併,採取的方法可以是git merge
,也可以是git rebase
.
git merge
一般來說,最簡單的操作就是執行下面的步驟:
git checkout featureA
git merge master
複製程式碼
或者直接:
git merge master featureA
複製程式碼
這樣就會產生一個三路合併:
git merge
的優點就是簡單,並且產生一個合併的歷史,但是如果master分支的歷史很活躍,你又想始終保持與master一致,那麼多多少少那麼多的合併歷史會影響到你分支歷史的整潔性。這時候git rebase
就可以登場了。
關於更多git merge
的詳細述說可以看我上一篇文章:git 分支管理
git rebase
作為merge
的替代,我們可以這樣執行rebase
:
git checkout featureA
git rebase master
複製程式碼
它會把整個featureA的分支直接移到現在master分支的後面:
git rebase
最大的特點就是會使你的專案歷史非常乾淨,呈現出一條線性提交,因為它不會引入合併提交,這讓你更容易使用git log
、git bisect
和gitk
來檢視專案歷史。
不過說git rebase
也是git
中的黑魔法,如果不遵守使用git rebase
的黃金法則,也會給你的專案歷史帶來災難性的影響,rebase
使你的feature
分支沒有合併提交歷史,所以你也看不出feature
合併進了上游的哪些修改。
互動式的rebase
這裡假設小A在他的featureA
分支已經有三個提交了,這時候如果直接rebase
就會把 這三個提交歷史都接到master
分支後面。
rebase
則可以對featureA
的分支歷史進行清理。
加上-i
,我們執行互動式的rebase
:
git checkout featureA
git rebase -i master
複製程式碼
它會開啟你git
的文字編輯器:
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
複製程式碼
這個列表顯示了你fetureA的歷史,你可以通過更改順序,更改pick或者使用fixup來合併你的歷史。比如如果#2
和#3
包含了修復性的更改,你想合併他們,那麼你可以加上一個fixup:
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
fixup 5c67e61 Message for commit #3
複製程式碼
如圖所示,#2
和#3
被合併為一次提交,這樣在合併的過程中還能簡化專案歷史,這是git merge
辦不到的。
Rebase黃金法則
當你使用Rebase
更加方便地處理你的分支時,你也必須懂得有哪些潛在的風險。使用rebase
的一條黃金法則就是,絕對不要在公共分支上使用它。假設你使用了,那麼便會發生下面的情況:
git rebase
將master
分支移到了featureA
分支的後面,而其他開發者還是基於原有的master
分支進行開發,這時候你的master
分支就和別人的分叉了,如果需要同步,則需要額外的一次git merge
,以讓你目前的master
和別人的master
合併,你的專案歷史更加令人迷惑。
所以,在進行git rebase
時,務必確認有沒有別人在此分支上工作,如果有的話,那麼你就得考慮一種無害的方式來進行你的提交,比如git revert
這樣的操作。