三路合併 —— Git 學習筆記 17
三路合併
和其他版本控制系統不同,Git 提供的合併衝突解決方案並不會聰明過頭,不會嘗試自動將所有問題都解決。Git 的設計哲學是智慧判斷一個合併是否可以非常容易地自動完成,如果自動化方案不可行,就不要自作聰明地去嘗試解決它,最好讓使用者自己去解決合併衝突。
檔案層面
通過比較共同的祖先(base)、當前分支(ours),待合併分支(theirs),Git 採用三路合併演算法生成合並結果。該演算法至少在檔案目錄層面非常簡單。其規則如下:
祖先(base) | HEAD(ours) | 分支(theirs) | 結果 | 說明 |
---|---|---|---|---|
A | A | A | A | |
A | A | B | B | 如果一方修改了某個檔案,選擇修改版的檔案 |
A | B | A | B | 如果一方修改了某個檔案,選擇修改版的檔案 |
A | B | B | B | 如果雙方擁有相同的變更,選擇修改過的版本 |
A | B | C | merge | 如果一方包含與另一方不一樣的變更,那麼在內容層面存在合併衝突 |
內容層面
如果是最後一行的情況,那麼 Git 就會在內容上嘗試合併。我們舉個例子,假設提交圖如下:
B-C-D master(*)
\
E-F dev
目前所在分支是 master,當嘗試把 dev 合併入 master 分支時,base 是提交 B,ours 是提交 D,theirs 是提交 F.
B、D、F 三個提交都有 foo.c 這個檔案,它們的內容分別如下:
請問 Git 會怎麼合併 ours 和 theirs 呢?
當然需要參考他們的共同祖先 base, 下圖示出了ours 和 theirs 分別與祖先不同的地方(用下劃線及藍色背景表示)。
祖先(base) | HEAD(ours) | 分支(theirs) | 結果 | 說明 |
---|---|---|---|---|
A | A | A | A | |
A | A | B | B | 如果一方修改了某一行,那麼這一行選擇修改版的 |
A | B | A | B | 同上 |
A | B | B | B | 如果某一行雙方擁有相同的變更,則選擇修改過的行 |
A | B | C | conflict | 如果某一行雙方都修改了,且修改得不一樣,則報告衝突,需要使用者解決 |
根據上表的規則,合併過程類似這樣:
可以看到,第四行,雙方都修改了,且各自修改的內容不一樣,所以 Git 不知道怎麼解決,所以就把問題拋給使用者了。
遞迴三路合併(Recursive three-way merge)
三路合併演算法的基礎是找到被合併檔案的共同祖先檔案。在遇到十字交叉合併(criss-cross merge)時,不存在獨一無二的最小共同祖先。如下圖所示,merge D 和 F 時,發現 C 和 E 都是它們的公共祖先,這可怎麼辦,C 和 E 哪一個作為 Base 呢?
B--C--D master
\ \/
\ /\
E--F dev
Git 的策略是:先合併 C 和 E 得到一個虛擬的公共祖先 G,把這個 G 作為 Base. 那如果合併 C 和 E 的時候發現他們的公共祖先也不止一個怎麼辦?所以就要遞迴進行了。
如下圖:合併 M 和 N,發現他們的共同祖先有2個——L 和 K,於是合併 L 和 K,又發現他們的祖先不止一個——I 和 J,於是合併 I 和 J,就這樣遞迴下去。
B--C---D--I--L--M master
\ \/ \/
\ /\ /\
E---F--J--K--N dev
參考資料
【1】《Git 高手之路》,人民郵電出版社
【2】https://stackoverflow.com/questions/4129049/why-is-a-3-way-merge-advantageous-over-a-2-way-merge
相關文章
- LevelDB 學習筆記2:合併筆記
- git學習筆記Git筆記
- 筆記-JavaWeb學習之旅17筆記JavaWeb
- GIT學習筆記一git initGit筆記
- Pro Git 學習筆記Git筆記
- Git的學習筆記Git筆記
- Git命令學習筆記Git筆記
- git學習筆記5Git筆記
- git學習筆記6Git筆記
- git學習筆記(一)Git筆記
- git學習筆記(二)Git筆記
- Git—學習筆記1Git筆記
- git學習筆記 1Git筆記
- git學習筆記1Git筆記
- Java基礎-學習筆記17Java筆記
- Git極簡學習筆記Git筆記
- git入門學習筆記Git筆記
- Git進階學習筆記Git筆記
- git 和 vim 學習筆記Git筆記
- Hadoop學習筆記—17.Hive框架學習Hadoop筆記Hive框架
- Git 的特點—— Git 學習筆記 02Git筆記
- 取得 Git 倉庫 —— Git 學習筆記 04Git筆記
- git rebase(變基)—— Git 學習筆記 19Git筆記
- git常用命令-Git學習筆記Git筆記
- 【批處理學習筆記】第十九課:字串合併筆記字串
- 【學習筆記】組合數學筆記
- 組合數學學習筆記筆記
- Git 簡單使用學習筆記Git筆記
- Git和Maven的學習筆記GitMaven筆記
- git status 命令總結 —— Git 學習筆記 06Git筆記
- git checkout 命令詳解—— Git 學習筆記 16Git筆記
- 《筆記》之學習高併發筆記
- JAVA 學習併發筆記(一)Java筆記
- (一)Java併發學習筆記Java筆記
- 撤銷操作 —— Git 學習筆記 12Git筆記
- 【Git】學習筆記–clone和本地修改Git筆記
- git reset 命令詳解(二)—— Git 學習筆記 08Git筆記
- git reset 命令詳解(一)—— Git 學習筆記 07Git筆記