原因是git merge
默認情況下使用了一種名爲「遞歸」合併的策略。它能夠執行三向合併:從一側取得補丁,並將補丁應用到另一側,以產生新文件。它也以遞歸方式執行此操作,在更復雜的情況下發生了很多分支和合並,並且有兩個合併基礎。
我最近遇到這個同樣的情況:
$ git merge-base --all 90d64557 05b3dd8f
711d1ad9772e42d64e5ecd592bee95fd63590b86
f303c59666877696feef62844cfbb7960d464fc1
$
隨着2個合併基地,一個3路合併是不可能的。因此,「遞歸」的策略解決了這個由第一遞歸到這兩個提交的合併:
$ git merge-base 711d1ad9 f303c596
3f5db59435ffa4a453e5e82348f478547440e7eb
$
OK,只有一個合併的基礎,因此,合併3路就可以開始。兩邊有什麼變化?
$ git diff --stat 3f5db594 711d1ad9
normalize/coll.py | 116 ++++++++++++++++++++++++++++++++++++++-----------
normalize/visitor.py | 49 ++++++++++-----------
tests/test_property.py | 10 +++--
3 files changed, 120 insertions(+), 55 deletions(-)
$ git diff --stat 3f5db594 f303c596
normalize/identity.py | 38 +++++++++++++++++++++++++++++++-------
tests/test_property.py | 2 ++
2 files changed, 33 insertions(+), 7 deletions(-)
$
這兩個差異列表都修改了同一個文件,所以他們不能使用的只是把每個文件的較新版本從各側(指數合併)一個簡單的策略來解決。相反,git從一邊取得新文件,然後嘗試從另一面應用該補丁。其結果是一個組合的提交,這可以模擬這樣的:
$ git checkout -b tmp
Switched to a new branch 'tmp'
$ git reset --hard f303c59666877696feef62844cfbb7960d464fc1
HEAD is now at f303c59 record_id: throw a more helpful error if record identity is not hashable
$ git merge 711d1ad9772e42d64e5ecd592bee95fd63590b86
Auto-merging tests/test_property.py
Merge made by the 'recursive' strategy.
normalize/coll.py | 116 ++++++++++++++++++++++++++++++++++++++-----------
normalize/visitor.py | 49 ++++++++++-----------
tests/test_property.py | 10 +++--
3 files changed, 120 insertions(+), 55 deletions(-)
$ git diff --stat 3f5db594 HEAD tests/test_property.py
tests/test_property.py | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
$
然後,它返回到原來的3路合併,使用該合併結果作爲它的開始點;這也涉及到更改同一文件:
$ git diff --stat HEAD 90d64557| grep selector
normalize/selector.py | 17 +--
tests/test_selector.py | 19 ++--
$ git diff --stat HEAD 05b3dd8f| grep selector
normalize/selector.py | 29 +++++++++++++++++------------
tests/test_selector.py | 9 +++++++++
$
但是再次更改了文件的不同部分,並因此服用DIFF並將其應用到另一邊是成功的。
因此,C git能夠通過首先在兩個起點的兩個合併基礎上進行3路合併,然後對兩個原始提交進行另一個3路合併進行合併,第一次合併的中間結果。
Github的自動分辨率不會這樣做。它並不一定是無能爲力的,我不確定它實現了多少遞歸策略,但它在謹慎的方面卻犯了錯誤,這正是你所期望的那樣的一個大綠色按鈕:-)。
遞歸合併策略的好處。 +1對我自己的答案有很好的補充。 – VonC