在合并分支時(如合并develop分支到master分支),我們可以有以下命令的選擇:
git merge // 等同于 git merge --ffgit merge --no-ffgit rebase
那么,這三者之間有哪些區(qū)別呢?對此,我將會通過下面的實驗進行比較說明:

分支合并實驗說明圖.png
實驗說明
在日常開發(fā)中,合并的兩個分支(下面將會以日常用到的master分支和develop分支這2個分支進行舉例),存在這2個情形:
- master分支和develop分支無分叉:只有develop分支有更新
- master分支和develop分支有分叉:兩個分支均有更新
接下來的實驗就是:分別在這兩個情形下,分別通過 git merge --ff 、git merge --no-ff 、git rebase 命令把develop分支合并到master分支,然后比較合并后的master的commit-tree。
merge --ff 、merge --no-ff 、rebase 各自合并的步驟如下:
-
使用
merge --ff合并的步驟git checkout master git merge develop // 等同 git merge --ff develop -
使用
merge --no-ff合并的步驟git checkout master git merge --no-ff develop -
使用
rebase合并的步驟git checkout develop git rebase master git checkout master git merge develop
實驗結(jié)果
分支無分叉的場景下:
合并前:

合并前.png
分別執(zhí)行merge/rebase后的情況對比:
- 應(yīng)用
git merge --ff

merge-ff.png
- 應(yīng)用
git merge --no-ff

merge-no-ff.png
- 應(yīng)用
git rebase

rebase.png
分支有分叉的場景下:
合并前:

合并前.png
分別執(zhí)行merge/rebase后的情況對比:
- 應(yīng)用
git merge --ff

merge-ff.png
- 應(yīng)用
git merge --no-ff

merge-no-ff.png
- 應(yīng)用
git rebase

rebase.png
實驗結(jié)論
通過結(jié)果圖的對比,可以得到以下結(jié)論:
| git merge --ff | git merge --no-ff | git rebase | |
|---|---|---|---|
| 分支無分叉 | 把develop上新的commit嫁接到master的最后commit上,效果等同于rebase,讓master的commit-tree保持線性 | 生成一個新的commit用于記錄這個合并操作 | 把develop上新的commit嫁接到master的最后一個commit上,讓master的commit-tree保持線性 |
| 分支有分叉 | 合并時,由于存在沖突,生成一個新的commit用于記錄此沖突,效果等同于 merge --no-ff | 生成一個新的commit用于記錄這個合并操作 | 通過rebase,把develop上新的commit嫁接到master的最后一個commit上,讓master的commit-tree保持線性 |
怎么選擇
通過合并結(jié)果對比可以知道,在合并時,我們就只需要『merge --no-ff 』和 『rebase』之間做選擇即可。那么在日常開發(fā)中怎么選擇呢?根據(jù)你的合并目的來:
| 合并目的 | 需要記錄此次合并,如合并release分支 | 希望commit-tree整潔和成線性,如合并feature分支 | 對commit-tree無要求,適合初學(xué)者 |
|---|---|---|---|
| 合并命令 | git merge --no-ff | git rebase | git merge |
參考資料:
https://www.idaima.com/article/6773
http://www.itdecent.cn/p/73ea5aca8bf3
http://www.itdecent.cn/p/0613d8249863