git merge的三種操作merge, squash merge, 和rebase merge
舉例來說:
假設(shè)在master分支的B點(diǎn)拉出一個(gè)新的分支dev,經(jīng)過一段時(shí)間開發(fā)后:
- master分支上有兩個(gè)新的提交M1和M2
- dev分支上有三個(gè)提交D1,D2,和D3
如下圖所示:

現(xiàn)在我們完成了dev分支的開發(fā)測(cè)試工作,需要把dev分支合并回master分支。
- merge
這是最基本的merge,就是把提交歷史原封不動(dòng)的拷貝過來,包含完整的提交歷史記錄。
$ git checkout master
$ git merge dev

此時(shí)還會(huì)生產(chǎn)一個(gè)merge commit (D4'),這個(gè)merge commit不包含任何代碼改動(dòng),而包含在dev分支上的幾個(gè)commit列表(D1, D2和D3)。查看git的提交歷史(git log)可以看到所有的這些提交歷史記錄。
- squash merge:
根據(jù)字面意思,這個(gè)操作完成的是壓縮的提交;解決的是什么問題呢,由于在dev分支上執(zhí)行的是開發(fā)工作,有一些很小的提交,或者是糾正前面的錯(cuò)誤的提交,對(duì)于這類提交對(duì)整個(gè)工程來說不需要單獨(dú)顯示出來一次提交,不然導(dǎo)致項(xiàng)目的提交歷史過于復(fù)雜;所以基于這種原因,我們可以把dev上的所有提交都合并成一個(gè)提交;然后提交到主干。
$ git checkout master
$ git merge --squash dev

在這個(gè)例子中,我們把D1,D2和D3的改動(dòng)合并成了一個(gè)D。
注意,squash merge并不會(huì)替你產(chǎn)生提交,它只是把所有的改動(dòng)合并,然后放在本地文件,需要你再次手動(dòng)執(zhí)行g(shù)it commit操作;此時(shí)又要注意了,因?yàn)槟阋闶謩?dòng)commit,也就是說這個(gè)commit是你產(chǎn)生的,不是有原來dev分支上的開發(fā)人員產(chǎn)生的,提交者本身發(fā)生了變化。也可以這么理解,就是你把dev分支上的所有代碼改動(dòng)一次性porting到master分支上而已。
- rebase merge
由于squash merge會(huì)變更提交者作者信息,這是一個(gè)很大的問題,后期問題追溯不好處理(當(dāng)然也可以由分支dev的所有者來執(zhí)行squash merge操作,以解決部分問題),rebase merge可以保留提交的作者信息,同時(shí)可以合并commit歷史,完美的解決了上面的問題。
$ git checkout dev
$ git rebase -i master
$ git checkout master
$ git merge dev
rebase merge分兩步完成:
第一步:執(zhí)行rebase操作,結(jié)果是看起來dev分支是從M2拉出來的,而不是從B拉出來的,然后使用-i參數(shù)手動(dòng)調(diào)整commit歷史,是否合并如何合并。例如下rebase -i命令會(huì)彈出文本編輯框:
pick <D1> Message for commit #1
pick <D2> Message for commit #2
pick <D3> Message for commit #3
假設(shè)D2是對(duì)D1的一個(gè)拼寫錯(cuò)誤修正,因此可以不需要顯式的指出來,我們把D2修改為fixup:
pick <D1> Message for commit #1
fixup <D2> Message for commit #2
pick <D3> Message for commit #3
rebase之后的狀態(tài)變?yōu)椋?/p>

D1'是D1和D2的合并。
第二步:再執(zhí)行merge操作,把dev分支合并到master分支:

注意:在執(zhí)行rebase的時(shí)候可能會(huì)出現(xiàn)沖突的問題,此時(shí)需要手工解決沖突的問題,然后執(zhí)行(git add)命令;所有沖突解決完之后,這時(shí)不需要執(zhí)行(git commit)命令,而是運(yùn)行(git rebase --continue)命令,一直到rebase完成;如果中途想放棄rebase操作,可以運(yùn)行(git rebase --abort)命令回到rebase之前的狀態(tài)。