1.合並或變基前的樣子
分支experiment與master兩個分支都產生了提交。
圖1. 未合並或變基前的樣子
2.合並
找到兩個分支的最末提交和最近的共同祖先,在執行git merge時所處的分支上,新建一個提交,在其中做一個簡單的三方合並。
合並后,注意c2,c3,c4沒有沖突,那么產生新的提交c5,如果有沖突,那么合並工作會暫停,解決沖突后可手動提交。
圖2. 合並后的樣子
相關命令:把experiment合並到master分支上。
$ git checkout master
$ git merge experiment
3.變基
未變基前參看圖1,它的原理是首先找到當前分支 experiment
、目的地分支 master
的最近共同最近祖先 C2
,然后對比當前分支相對於該祖先的歷次提交,提取相應的修改並存為臨時文件,然后將當前分支指向目標分支上C2后的第一個提交 C3
, 最后以此將之前另存為臨時文件的修改依序逐個應用到后面的每個提交。
圖3. 變基中的樣子
圖4. 變基后的樣子
相關命令:
$ git checkout experiment
$ git rebase master
$ git checkout master
$ git merge experiment
金科玉律:
- 變基有風險,只在本地變基,不要變基服務器上的分支。
- 變基操作的實質是丟棄一些現有的提交,然后相應地新建一些內容一樣但實際上不同的提交。如果有人依賴那些丟棄的提交,會產生問題。
- 如果有人變基服務器上的分支,其它人更新數據時要執行
git pull --rebase
命令,這樣盡管不能避免傷痛,但能有所緩解。 - 只要你把變基命令當作是在推送前清理提交使之整潔的工具,並且只在從未推送至共用倉庫的提交上執行變基命令,你就不會有事。
4.對比
有一種觀點認為,倉庫的提交歷史即是 記錄實際發生過什么。 它是針對歷史的文檔,本身就有價值,不能亂改。 從這個角度看來,改變提交歷史是一種褻瀆,你使用謊言掩蓋了實際發生過的事情。 如果由合並產生的提交歷史是一團糟怎么辦? 既然事實就是如此,那么這些痕跡就應該被保留下來,讓后人能夠查閱。
另一種觀點則正好相反,他們認為提交歷史是 項目過程中發生的故事。 沒人會出版一本書的第一批草稿,軟件維護手冊也是需要反復修訂才能方便使用。 持這一觀點的人會使用 rebase 及 filter-branch 等工具來編寫故事,怎么方便后來的讀者就怎么寫。
現在,讓我們回到之前的問題上來,到底合並還是變基好?希望你能明白,並沒有一個簡單的答案。 Git 是一個非常強大的工具,它允許你對提交歷史做許多事情,但每個團隊、每個項目對此的需求並不相同。 既然你已經分別學習了兩者的用法,相信你能夠根據實際情況作出明智的選擇。
5.總的原則
只對尚未推送或分享給別人的本地修改執行變基操作清理歷史,從不對已推送至別處的提交執行變基操作,這樣,你才能享受到兩種方式帶來的便利。