Preface
git 進行 merge 有三種操作 merge, squash merge, 和 rebase merge. 底下說明其在 commit tree 上的差別. 舉例來說, 假設在 master 分支的 B點 拉出一個新的分支 dev,經過一段時間開發後:
如下圖所示:
現在我們完成了 dev 分支的開發測試工作,需要把 dev 分支合併回 master 分支。
方法一: merge
這是最基本的 merge,就是把提交歷史原封不動的拷貝過來,包含完整的提交歷史記錄:
此時還會生產一個 merge commit (D4'),這個 merge commit 不包含任何代碼改動,而包含在 dev 分支上的幾個 commit 列表(D1, D2 和 D3)。查看 git 的提交歷史(git log)可以看到所有的這些提交歷史記錄。
方法二: squash merge
根據字面意思,這個操作完成的是壓縮的提交;解決的是什麼問題呢,由於在 dev 分支上執行的是開發工作,有一些很小的提交,或者是糾正前面的錯誤的提交,對於這類提交對整個工程來說不需要單獨顯示出來一次提交,不然導致項目的提交歷史過於復雜;所以基於這種原因,我們可以把 [b]dev 上的所有提交都合併成一個提交;然後提交到主幹[/b]。
在這個例子中,我們把 D1,D2 和 D3 的改動合併成了一個 D。
注意,squash merge 並不會替你產生提交,它只是把所有的改動合併,然後放在本地文件,需要你再次手動執行 git commit 操作;此時又要注意了,因為你要你手動commit,也就是說這個 commit 是你產生的,不是有原來 dev 分支上的開發人員產生的,提交者本身發生了變化。也可以這麼理解,就是你把 dev 分支上的所有代碼改動一次性 porting 到 master 分支上而已。
方法三: rebase merge
由於 squash merge 會變更提交者作者信息,這是一個很大的問題,後期問題追溯不好處理 (當然也可以由分支 dev 的所有者來執行 squash merge 操作,以解決部分問題),rebase merge 可以保留提交的作者信息,同時可以合併 commit 歷史,完美的解決了上面的問題。
rebase merge 分兩步完成:
第一步:
執行 rebase 操作,結果是看起來 dev 分支是從 M2 拉出來的,而不是從 B 拉出來的,然後使用 -i 參數手動調整 commit 歷史,是否合併如何合併。例如下 rebase -i 命令會彈出文本編輯框:
- pick
Message for commit #1 - pick
Message for commit #2 - pick
Message for commit #3
- pick
Message for commit #1 - fixup
Message for commit #2 - pick
Message for commit #3
D1' 是 D1 和 D2 的合併。
第二步:
再執行 merge 操作,把 dev 分支合併到 master 分支:
注意:在執行 rebase 的時候可能會出現衝突的問題,此時需要手工解決衝突的問題,然後執行 (git add) 命令;所有衝突解決完之後,這時不需要執行 (git commit) 命令,而是運行 (git rebase --continue) 命令,一直到 rebase 完成;如果中途想放棄 rebase 操作,可以運行 (git rebase --abort) 命令回到 rebase 之前的狀態。
A Real rebase merge Case
底下我們來看一個實際的 rebase merge 範例:
接著我們要對 master 進行 rebase :
接著回去 master branch, 並對 dev 進行 merge:
通常如果 dev 日後還需要使用, 則需要再回到 dev 並將 master merge 回來:
如果要看更完整的 commit 紀錄, 可以使用 git log --graph --all --decorate:
沒有留言:
張貼留言