原因是git merge
默认情况下使用称为“递归”合并的策略。它能够执行 3 路合并:从一侧获取补丁,并将该补丁应用到另一侧,以生成新文件。它也递归地执行此操作,在更复杂的情况下,已经发生了很多分支和合并,并且有多个合并基础用于合并的两个提交。
我最近遇到了同样的情况:
$ git merge-base --all 90d64557 05b3dd8f
711d1ad9772e42d64e5ecd592bee95fd63590b86
f303c59666877696feef62844cfbb7960d464fc1
$
使用 2 个合并基础,不可能进行 3 路合并。因此,“递归”策略通过首先递归到这两个提交的合并来解决这个问题:
$ git merge-base 711d1ad9 f303c596
3f5db59435ffa4a453e5e82348f478547440e7eb
$
好的,只有一个合并基地,所以可以开始三路合并。两边有什么变化?
$ 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-way 合并,使用这个合并结果作为它的起点;这也涉及对同一文件的更改:
$ 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 +++++++++
$
然而,再次更改文件的不同部分,因此获取差异并将其应用于另一侧是成功的。
因此,C git 能够通过首先在两个起点的两个合并基础上进行 3 路合并,然后对正在合并的两个原始提交和中间结果进行另一个 3 路合并来解决此合并。第一次合并。
Github 的自动解析并没有做到这一点。它不一定没有能力,而且我不确定它确实实现了多少递归策略,但出于谨慎的考虑,这是错误的,这正是您期望像这样的绿色大按钮所做的事情:-)。