【问题标题】:Git silently merges as updates what should be conflictsGit 默默地合并为更新应该是什么冲突
【发布时间】:2018-03-28 00:30:54
【问题描述】:

简而言之,这就是发生在我们身上的事情:

  • master上的这个文件开始:

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

  • featureA,将文件更改为:

    class SomeClass {
        ...
    }
    
    extension SomeClass {
        // implement feature A
    }
    
  • 创建分支featureBoff `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
}

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

这可以预防吗?怎么样?

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

【问题讨论】:

  • 是否使用了merge strategy
  • @MarcinArmatys 据我所知,只使用了默认的git merge

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


【解决方案1】:

在您可以证明不是人为错误的错误合并案例中,要考虑的主要事情是 Git 的合并使用 Git 的差异作为输入。如果差异在琐碎的项目上同步,例如恰好有正确缩进的右大括号行,Git 可以将合并结果放在缩进良好的地方,因此 编译,但在语义上是错误的 -适合,因此不起作用

如果您说服 Git 不要在琐事上同步,它更有可能检测到实际冲突。您可以通过更改合并时使用的差异算法来做到这一点。您可以尝试选择patiencehistogram 算法,使用-X patience-X histogram。有关详细信息的(简要)讨论,请参阅我的 not-making-much-progress-on-weekends book 的第 3 章(第 65 页)目前的结尾。

【讨论】:

  • 谢谢,我不知道有不同的差异算法可供选择。不幸的是,他们似乎都没有正确识别差异。而且,老实说,我不知道基于行的差异如何。我不确定git merge 如何从差异(显示差异)到决定什么是编辑和什么是冲突。
  • 在内部,由于 Git 具有文件的合并基础版本和文件的两个分支提示版本,它只需要注意每个差异的行跨范围。调用两侧 L(左/本地)和 R(右/远程)。假设我们按起始行号对联合后的差异进行排序。 “当前”更改(从 L 或 R)跨越基本文件的某个行范围 [K..K+N)。如果“下一个”差异,无论来自哪个不是,也跨越相同的范围,则存在冲突。否则,应用此更改并转到实际的下一个(可能来自同一个 L/R 而不是另一个)。
  • 根据我的测试(我还没有挖掘源代码)这个算法稍微调整一下,假装结束而不是开始,延长了一行,所以总是有冲突如果双方在同一位置添加线。 (我们不知道应该首先进行哪个添加。)此外,我不确定我是否正确地表达了其中的任何一个 - 它确实有助于将其转换为详细的算法,或者研究那个就在那里(我相信 Git 采用了 RCS 合并算法,所以 Tichy 的工作可能适用)。
  • 谢谢,你写的很有道理。这当然解释了为什么我有时会得到“明显的”误报。 (可以说,这些事情应该记录在来源之外的某个地方......)。
  • 另外,我可以尝试改进我对耐心差异算法的描述。它的核心是比较/定位 unique 行(但唯一性是每个“子框”,所以我觉得很难描述)。
【解决方案2】:

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

  • 在带有 Git 2.7.4 和 Meld 3.14.2 的 Ubuntu 上,我发现与 git mergegit merge -s patience 存在冲突。
  • 在装有 Git 2.11.0 和 Meld 3.16.0 的 Mac 上,我发现 no 与任一合并命令发生冲突。

    相反,有

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

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

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

似乎该版本的 Meld 无法解析某些差异。它没有向我显示冲突,因此在将其标记为已解决之前我没有正确修复它。

注意事项:复制这显然需要更多“匹配”行;我的问题中的小例子没有做到这一点。

【讨论】:

    【解决方案3】:

    正如您所说,当您尝试单独复制它时,这会适当地产生冲突。

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

    【讨论】:

    • 不,没有一个分支合并到另一个分支。
    猜你喜欢
    • 2015-02-09
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2016-04-26
    • 2015-04-11
    • 2023-02-11
    相关资源
    最近更新 更多