考虑下面的情况:
A 1:1 2:2
代表节点A
包含两个文件,文件1
的内容是1
,文件2
的内容是2
。
B
、C
节点分别做了修改,现在需要合并,把C
merge到B
,结果会是什么样的呢?
根据三路合并的原理,首先找C
和B
的公共祖先,然后对比文件。C
和B
的公共祖先是A
,三路合并表如下:
ancestor(A) | theirs(C) | ours(B) |
---|---|---|
1:1 | 1:8 | 1:6 |
2:2 | 2:24 | 2:2 |
根据上表,文件1
theirs 和 ours 都有修改,需要解决冲突;文件2
ours 和 ancestor 一致,theirs做了修改,以theirs为准,merge结果为24
。
结果如下:
现在假设merge时误操作,在解决文件1
冲突的时候,手动将文件2
修改为了2
,文件1
解决完冲突,内容为8
。
误操作后,结果如下:
为了修复误操作,将文件2
修复成24
,一个比较直观的想法是先revertD
,然后重新merge。
使用命令git revert D -m 1
revertD
并恢复到B
,然后重新merge:
结果mergeC
和^D
时,git返回Already up to date
,什么都没做。这是为什么呢?
这是因为C
和^D
的公共祖先为C
,merge时会像这样三路合并:
ancestor(C) | theirs(C) | ours(^D) |
---|---|---|
1:8 | 1:8 | 1:6 |
2:24 | 2:24 | 2:2 |
根据上面的表格,git发现,theirs没有修改,ours修改了,以ours为准,因此文件1
内容仍为6
,文件2
内容仍为24
,这次merge操作,并不会生成E
节点。
如果从B
拉一个新分支,重新mergeC
,生成F
,会怎么样呢?我们操作一下:
现在F
上是正确的内容(2:24
),此时如果再将F
merge到^D
上,生成G
,G
的内容会是什么呢?
首先看F
和^D
的公共祖先,有B
和C
两个。
使用命令git merge-base -a B C
,结果显示确实有B和C两个最佳公共祖先。
有两个最佳公共祖先时怎么处理?git-merge
的man-page
的章节MERGE STRATEGIES
有介绍:
When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge.
git首先会做B
和C
的merge。B
和C
的公共祖先是A
,三路合并表如下:
ancestor(A) | theirs(C) | ours(B) |
---|---|---|
1:1 | 1:8 | 1:6 |
2:2 | 2:24 | 2:2 |
结果为文件1
有冲突,文件2
内容为24
。
这个结果再作为base,参与F
和^D
的合并:
base | theirs(F) | ours(^D) |
---|---|---|
1:6?8?有冲突 | 1:8 | 1:6 |
2:24 | 2:24 | 2:2 |
结果为:文件1
需要解冲突,文件2
内容为2
。