版本控制中的三方合并

在学习Git时,一般会学到Git的合并方式,除了快进之外,还有三方合并(three way erge)。三方合并也是Subversion等传统版本控制软件的合并策略。本文讲解什么是三方合并,为何需要三方合并,为何不使用两方合并。

考虑以下两个分支,其中1bdd3be5d6c1b0e2为这两个分支的Git版本号

1bdd3be5 d6c1b0e2
1
2
3
4
5
5
4
3
2
1

要将他们合并,请问合并后的文件是什么样?

这里不能根据上下文语义确定内容,读者看到这里估计都懵了。

但是如果知道1bdd3be5d6c1b0e2的共同祖先呢?如下图,1bdd3be5修改自ba8beb31d6c1b0e2也修改自ba8beb31。请问这两个分支将如何合并?

ba8beb31
<---- 5
4
3
4
1
---->
1bdd3be5 d6c1b0e2
1
2
3
4
5
5
4
3
2
1

经过分析,我们把修改的行用*标识出来。

ba8beb31
<---- 5
4
3
4
1
---->
1bdd3be5 d6c1b0e2
*1
*2
 3
 4
*5
 5
 4
*3
*2
 1

这样一看我们就清楚了,只需要把差异项合并,合并后的文件就是
1
2
3
2
5

由此可见共同祖先对于分支合并是非常重要的,没有共同祖先,我们就难以确定如何合并,遑论机器了。这同时也说明,“两方合并”是不可行的。

不同的共同祖先对合并有影响吗,答案是肯定的。见下一个例子,设37b21605为那两个分支的共同祖先,差异行已标出。

37b21605
<---- 5
2
3
2
1
---->
1bdd3be5 d6c1b0e2
*1
 2
 3
*4
*5
 5
*4
 3
 2
 1

这个情况下的合并结果为
1
4
3
4
5

所以,如果版本控制系统不能正确确定两个版本的共同祖先,则会造成意外的合并结果。

现在回归到Git与Subversion,鉴于Git以链表方式存储版本,非常容易确定两个分支的最近共同祖先

https://github.com/gqqnbig/git-conflict-test

发表评论

电子邮件地址不会被公开。

 剩余字数

ea dz dy dx dw dv du dt ds dr dq dp dn dm dl dk dj di dh dg df de dd dc da cz cy cx cw cv cu ct cs cr cq cp co cn cm cl ck cj ci ch cg cf ce cd cc cb ca bz bx bw bv bu bt bs br bq bp bo bn bm bl bk bj bi bh bg bf bd bc bb ba az ay ax aw av au ar aq ap ao am al ak aj ai ah ag af ae ad ac ab /跳跳 /抓狂 /快哭了/ /微笑/ /奋斗 /呲牙/ /吐