三路合并 —— Git 学习笔记 17
三路合并
和其他版本控制系統不同,Git 提供的合并沖突解決方案并不會聰明過頭,不會嘗試自動將所有問題都解決。Git 的設計哲學是智能判斷一個合并是否可以非常容易地自動完成,如果自動化方案不可行,就不要自作聰明地去嘗試解決它,最好讓用戶自己去解決合并沖突。
文件層面
通過比較共同的祖先(base)、當前分支(ours),待合并分支(theirs),Git 采用三路合并算法生成合并結果。該算法至少在文件目錄層面非常簡單。其規則如下:
| 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 分別與祖先不同的地方(用下劃線及藍色背景表示)。
| 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 devGit 的策略是:先合并 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
【3】http://blog.fedeoo.cn/2017/02/22/git-合并策略-之-recursive/
總結
以上是生活随笔為你收集整理的三路合并 —— Git 学习笔记 17的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jsp 跳到servlet路径_请问如何
- 下一篇: android p安装教程,Androi