git merge VS git rebase
使用 Git 很久了,一直以為對於常用的這些命令已經很瞭解了,可是突然發現對於很多東西的理解都太過淺顯,於是不得不回過頭來補課。
大概就是傳說中的「too young too simple」。
我們知道 merge 和 rebase 都是 git 中用來合併程式碼的常用操作,用於從一個分支獲取並且合併到當前分支,但是他們有什麼區別或者優缺點分別是什麼,在使用的時候應該怎麼選擇呢?如果你跟我一樣不是很清楚可以繼續讀下去了。

merge 和 rebase 的區別
場景:
如圖所示,假設你的專案有一個公用的主分支 master,而你正在 feature 分支上開發一個新功能,同時 master 分支也會有新的更新。

在某些場景下,你必須要將 master 分支上的程式碼同步到自己的 feature 分支上或者是將自己的 feature 分支上的修改合併到 master 分支,這個時候你就會有兩種選擇: merging
或 rebasing
。
merge
以將 feature 分支合併到 master 分支為例,先將分支切到 master 上,然後執行 merge 命令,程式碼如下:
git checkout master git merge feature
或者你也可以把他們壓縮成一行
git merge feature master
此時就會自動在 master 分支上產生一個新的 commit(merge commit),如下圖所示:

merge 的特點:
- 自動建立一個 commit
- 如果 merge 過程中出現衝突僅需要修改一個 commit
merge 的優點是它記錄了真實的 commit 情況,包括每個分支的詳情,哪個分支上做了些什麼事情都可以從提交歷史中看出來;但是缺點是每一個 merge 操作都會自動生成一個 merge commit,對於需要頻繁合併的分支來說,commits 歷史就會顯得比較雜亂。
rebase
如果使用 rebasing 的方式,執行下列命令:
git checkout master git rebase feature
最終的 commit 結果如圖所示:

從圖中可以看出,rebase 執行的結果是一條直線,並且沒有自動生成的 merge commit,這也正是 rebase 的特點,它會根據 commit 的時間點進行合併,最終形成一條直線。
這樣做的優點是使得最終的 commit 歷史變得更加簡潔和美觀,但是也造成了出了問題不好追蹤 commit 歷史的問題,因為 commits 已經被 re-write 了。
在出現衝突的時候,使用如下步驟解決衝突:
git add git rebase --continue
如果不想進行此次 rebase 操作執行 git rebase --abort
如何選擇
知道了 merge 和 rebase 的區別,那麼在實際專案上我們應該如何選擇呢?

rebase 的黃金法則
git rebase 的黃金法則是,絕不要在公共的分支上使用它。
假設你想要將 master 分支合併到你的 feature 分支上,你執行了 rebase 操作,這時 master 分支上的提交會追加到 feature 分支的後面,但是這時其他人還在 master 分支上工作,由於你的 rebase 操作移動了 master 分支,git 會認為你的主分支的歷史和其他人的有分歧,就會產生衝突。
而同步這兩個分支的唯一辦法就是使用 merge 操作,生成一個額外的 commit 包含所有的提交,這或許會讓人很頭大。
所以我們在選擇是否使用 rebase 的時候可以問問自己「是否有人正在這個分支上工作?」
如果答案是肯定的,那最好不要使用 rebase,如果不是,那麼就可以隨意了。
總結
不能說哪種方法好或不好,只有基於自己目前的專案狀況哪個更合適一些,如果你希望保留完整的 commits history,對於產生的 merge commit 並不 care 的話就可以使用 merge,如果更在意 history 的整潔性並且保證使用 rebase 不會影響其他人的話就用 rebase。