Git默默地合并为更新应该是冲突

时间:2017-10-16 13:06:27

标签: git merge git-merge git-merge-conflict

简化,这就是我们发生的事情:

  • master上的此文件开始:

    class SomeClass {
        ...
    }
    
  • 创建分支featureA off`master。

  • featureA上,将文件更改为:

    class SomeClass {
        ...
    }
    
    extension SomeClass {
        // implement feature A
    }
    
  • 创建分支featureB off`master。
  • featureB上,将文件更改为:

    class SomeClass {
        ...
    }
    
    class OtherClass {
        // implement feature B
    }
    
  • featureB合并到master
  • featureA合并到master

我们期待的是:

class SomeClass {
    ...
}

extension SomeClass {
    // implement feature A
}

class OtherClass {
    // implement feature B
}

或以相反的顺序添加两个,这是公平的 实际上,Git应该报告一个冲突:它不了解语义,并且两个“同时”的变化无法协调。

我们获取的是:

class SomeClass {
    ...
}

class OtherClass {
    // implement feature B
}

没有冲突。也就是说,后来的提交(在另一个之前合并)默默地胜出。

这可以预防吗?怎么样?

注意:如果我使用上述步骤在干净的仓库中尝试此操作,我会在最后一步中遇到合并冲突。因此,问题的根源在于我们在回购中所做的其他事情;暗示赞赏,我看不出会有什么影响。或者问题是差异算法被更复杂的代码绊倒;在生产Swift代码中,我们在一侧有两个扩展,另一侧有嵌套类型的枚举。

3 个答案:

答案 0 :(得分:1)

在错误合并的情况下要考虑的主要问题是你可以证明不是人为错误,Git的合并使用Gi​​t的差异作为输入。如果差异在普通项目上同步,例如恰好具有右缩进的紧支撑线,Git可以将合并结果放在缩进的位置,因此编译,但是在语义上不合适 - 适合,因此不功能

如果你说服Git不要在琐事上同步,那么它更有可能发现实际的冲突。您可以通过更改合并时使用的diff算法来完成此操作。您可以尝试使用patiencehistogram选择-X patience-X histogram算法。有关详细信息的(简短)讨论,请参阅我在周末book进行的非常多进展的第3章(第65页)的结尾。

答案 1 :(得分:1)

使用相同的尝试合并进行一些交叉测试:

  • 在使用Git 2.7.4和Meld 3.14.2的Ubuntu上,我发现与git mergegit merge -s patience存在冲突。
  • 在使用Git 2.11.0和Meld 3.16.0的Mac上,我看到 no 与merge命令冲突。

    相反,有

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

    在文件的末尾,所以我认为Meld在这里没有正确解析差异。

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

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

Nota bene:重现这一点显然需要更多"匹配"线;我的问题中的一个小例子没有做到。

答案 2 :(得分:0)

如您所说,当您尝试单独重现它时,这会恰当地产生冲突。

我最好的猜测是,你的一个分支的开发者将其他开发者分支合并到它自己的分支中,并通过删除第二个类定义来解决冲突。