【发布时间】:2017-07-12 06:44:51
【问题描述】:
我们最近遇到了一些与 git 的合并问题,虽然它可能做了“正确的事情”(TM),但这并不是我所期望的。我已将问题简化为位于 https://github.com/geretz/merge-quirk 的小型公共 github 存储库。
quirk.c 存在于 master 上。 merge-src 和 merge-dst 都是从 master 上的同一版本分支出来的,这是最终合并的共同祖先。 merge-src 添加注释和一些代码。 merge-dst 重新格式化代码并更改现有的 cmets,但没有添加的注释或代码。
git merge 检测并声明冲突。
git clone https://github.com/geretz/merge-quirk.git
cd merge-quirk
git checkout merge-dst
git merge origin/merge-src
Auto-merging quirk.c
CONFLICT (content): Merge conflict in quirk.c
Automatic merge failed; fix conflicts and then commit the result.
但是,如果天真/信任的开发人员在冲突标记的 quirk.c 中选择 origin/merge-src 代码块,则 thisLineMightDisapper (sic) 函数调用将丢失。
在我的心智模型中,如果 thisLineMightDisapper 函数调用在 HEAD 和 origin/src 中都存在于冲突状态中,它应该存在于两个冲突块中,如果它不存在于冲突状态中,它应该存在于两个冲突之外块。为什么它只出现在 HEAD 块内?
<<<<<<< HEAD
// a few comment lines - change 1
// that existed - change 2
// in the common ancestor - change 3
// that get changed - change 4
if(1)
{
if (f(1, 2))
{
if (thisLineMightDisapper(42))
=======
// a few comment lines
// that existed
// in the common ancestor
// added this line in merge-src branch
// that get changed
if(1) {
if (f(1, 2))
>>>>>>> origin/merge-src
{
t = time(0);
}
}
}
if (anotherFunction(1,2))
{
t = time(0)
f(0);
}
}
文件
master/quirk.c
// a few comment lines
// that existed
// in the common ancestor
// that get changed
if(1) {
if (f(1, 2))
{
if (thisLineMightDisapper(42)) {
t = time(0);
}
}
}
}
merge-src/quirk.c
// a few comment lines
// that existed
// in the common ancestor
// added this line in merge-src branch
// that get changed
if(1) {
if (f(1, 2))
{
if (thisLineMightDisapper(42)) {
t = time(0);
}
}
}
if (anotherFunction(1,2))
{
t = time(0)
f(0);
}
}
合并-dst/quirk.c
// a few comment lines - change 1
// that existed - change 2
// in the common ancestor - change 3
// that get changed - change 4
if(1)
{
if (f(1, 2))
{
if (thisLineMightDisapper(42))
{
t = time(0);
}
}
}
}
【问题讨论】:
-
当 git 无法弄清楚如何自动解决更改时会发生合并冲突。你,开发者,必须真正阅读它并弄清楚如何解决。
-
我建议也将
merge.conflictStyle设置为diff3:这显示了Git 在原始(公共基础)文件中看到的内容,与合并的两个端点,即HEAD / @987654329 @和其他/--theirs。请注意,如果您现在正在查看冲突,但尚未解决,您也可以使用git checkout --conflict=diff3 quirk.c将其内容替换为新的冲突合并,但这次使用所选样式。 -
@torek diff3 不能解决根本问题。 diff3 共同祖先块中也缺少 thisLineMightDisapper 调用,仅出现在 HEAD 块中。
-
好吧,看看 Dietrich Epp 的回答;但以上是评论,而不是答案,因为当我也可以看到原始基础时,我发现更容易推理 Git 看到(并因此做了)什么。 Git 只知道将碱基与两个技巧匹配,并将它认为的变化结合起来。我还要在这里指出,即使 Git 认为它正确解决了两个差异,也不能保证它确实。
-
@torek 感谢您为我指出正确的方向(git 匹配两个提示的基础)。由于 merge-dst 重新格式化,因此在两个不同的大块中添加和删除了 thisLineMightDisapper 代码。删除显然没有冲突,因此合并的一部分“有效”,添加与不包含该行的不同块冲突,因此该函数仅出现在一个冲突块中。