2017-10-16 74 views
1

简化,这是发生在我们身上:的Git默默合并为更新应该是什么冲突

  • 开始与这个文件有关master

    class SomeClass { 
        ... 
    } 
    
  • 创建分支featureA关`主。

  • featureA,更改文件:

    class SomeClass { 
        ... 
    } 
    
    extension SomeClass { 
        // implement feature A 
    } 
    
  • 创建分支featureB关`主。
  • featureB,更改文件:

    class SomeClass { 
        ... 
    } 
    
    class OtherClass { 
        // implement feature B 
    } 
    
  • 合并featureBmaster
  • featureA合并为master

我们预计是:

class SomeClass { 
    ... 
} 

extension SomeClass { 
    // implement feature A 
} 

class OtherClass { 
    // implement feature B 
} 

或两个以相反的顺序添加,这是公平的。
实际上,Git应该可能会报告一个冲突:它没有关于语义的知识,并且两个“同时”更改无法调和。

我们得到是:

class SomeClass { 
    ... 
} 

class OtherClass { 
    // implement feature B 
} 

而不会发生冲突。也就是说,后面的提交(在另一个提交之前合并)默默地胜出。

这可以预防吗?怎么样?

注意:如果我用上述步骤在一个干净的回购库中尝试此操作,则会在最后一步中遇到合并冲突。所以,无论这个问题是根植于我们在回购的其他方面。暗示赞赏,我不明白什么可能会影响事情。或者,问题是diff算法被更复杂的代码绊住了;在生产Swift代码中,我们在一边有两个扩展,另一边有嵌套类型的枚举。

+0

是否使用过任何[合并策略](https://git-scm.com/docs/merge-strategies)? –

+0

@MarcinArmatys据我所知,只有默认的'git merge'已被使用。 – Raphael

回答

1

一些交叉的检测与同试图合并:

  • 在Ubuntu上使用Git 2.7.4和MELD 3.14.2,我看到git mergegit merge -s patience冲突。
  • 在Mac上,使用Git 2.11.0和Meld 3.16.0,我看到没有与任一合并命令发生冲突。

    相反,有

    ==== BASE ==== 
    } 
    ==== BASE ==== 
    

    在文件的结尾,所以我认为MELD不能解析DIFF正确这里。

  • 在同一台Mac和同一合并期间,AppCode 2017.3中的差异查看器显示冲突。

似乎该版本的Meld在解析某些差异时遇到了麻烦。它没有向我显示冲突,所以在将它标记为已解决之前,我没有正确解决它。

注意:重现这显然需要更多的“匹配”线;我的问题中的一个小例子并没有这样做。

0

正如你所说,当你试图单独重现它时,这会正确地产生冲突。

我最好在这一点猜测是你的分支之一的developper合并其他developper分支到自己,并通过删除第二类定义解决冲突。

+0

不,没有任何分支合并到另一个分支中。 – Raphael

1

最主要的错误合并的情况下,你能证明不是人为错误是Git的合并使用Gi​​t的diff文件作为输入来考虑。如果diff文件上的琐碎物品,如关闭括号线碰巧有正确的缩进同步,混帐可以把合并的结果是很好的缩进的地方,因此编译,但在语义上是不适合,因此不功能

如果你说服Git不要在琐事上同步,它更可能检测实际冲突。您可以通过更改合并时使用的差异算法来实现此目的。您可以尝试选择patiencehistogram算法,使用-X patience-X histogram。有关细节的(简短的)讨论,请参阅第3章(第65页)的结尾部分,我周末的进度不太大,book

+0

谢谢,我不知道有不同的差异算法可供选择。不幸的是,他们中没有一个似乎能够正确识别差异。而且,说实话,我不知道一个基于行的diff *可以如何*。我不确定'git merge'是如何从差异(显示,差异)到决定什么是编辑以及什么是冲突。 – Raphael

+0

在内部,由于Git具有文件的合并基础版本和文件的两个分支顶端版本,因此它只需要注意每个diff的行跨度范围。调用双方L(左/本地)和R(右/远程)。假设我们通过起始行号对联合编辑的差异进行排序。 “当前”更改(从L或R)跨越基本文件的某个行范围[K..K + N)。如果“下一个”差异来自这个*不是来自哪一个,也跨越相同的范围,则存在冲突。否则,应用此更改并转到实际的下一个(可能来自相同的L/R而不是其他)。 – torek

+1

根据我的测试(我还没有通过源代码挖掘出来),这个算法稍微调整了一下,假设结束,但不是开始,延长一行,所以如果双方在相同的位置。 (我们不知道哪些加法应该发生* first *。)另外我不确定我是否正确地表述了这些 - 它确实有助于将它转换为详细的算法,或者研究那里的一个算法(I相信Git采用了RCS合并算法,所以Tichy的工作可能适用)。 – torek