一、是什么
在使用 git 進行版本管理的項目中,當完成一個特性的開發并將其合并到 master 分支時,會有兩種方式:
git merge
git rebase
git rebase 與 git merge都有相同的作用,都是將一個分支的提交合并到另一分支上,但是在原理上卻不相同
用法上兩者也十分的簡單:
git merge
將當前分支合并到指定分支,命令用法如下:
git merge xxx
git rebase
將當前分支移植到指定分支或指定commit之上,用法如下:
git rebase -i <commit>
常見的參數有–continue,用于解決沖突之后,繼續執行rebase
git rebase --continue
二、分析
git merge
通過git merge將當前分支與xxx分支合并,產生的新的commit對象有兩個父節點
如果“指定分支”本身是當前分支的一個直接子節點,則會產生快照合并
舉個例子,bugfix分支是從master分支分叉出來的,如下所示:
合并 bugfix分支到master分支時,如果master分支的狀態沒有被更改過,即 bugfix分支的歷史記錄包含master分支所有的歷史記錄
所以通過把master分支的位置移動到bugfix的最新分支上,就完成合并
如果master分支的歷史記錄在創建bugfix分支后又有新的提交,如下情況:
這時候使用git merge的時候,會生成一個新的提交,并且master分支的HEAD會移動到新的分支上,如下:
從上面可以看到,會把兩個分支的最新快照以及二者最近的共同祖先進行三方合并,合并的結果是生成一個新的快照
git rebase
同樣,master分支的歷史記錄在創建bugfix分支后又有新的提交,如下情況:
通過git rebase,會變成如下情況:
在移交過程中,如果發生沖突,需要修改各自的沖突,如下:
rebase之后,master的HEAD位置不變。因此,要合并master分支和bugfix分支
從上面可以看到,rebase會找到不同的分支的最近共同祖先,如上圖的B
然后對比當前分支相對于該祖先的歷次提交,提取相應的修改并存為臨時文件(老的提交X和Y也沒有被銷毀,只是簡單地不能再被訪問或者使用)
然后將當前分支指向目標最新位置D, 然后將之前另存為臨時文件的修改依序應用
三、區別
從上面可以看到,merge和rebasea都是合并歷史記錄,但是各自特性不同:
merge
通過merge合并分支會新增一個merge commit,然后將兩個分支的歷史聯系起來
其實是一種非破壞性的操作,對現有分支不會以任何方式被更改,但是會導致歷史記錄相對復雜
rebase
rebase 會將整個分支移動到另一個分支上,有效地整合了所有分支上的提交
主要的好處是歷史記錄更加清晰,是在原有提交的基礎上將差異內容反映進去,消除了 git merge所需的不必要的合并提交