mercurial merge选择了错误的更改,解决这个问题的正确方法是什么?

时间:2010-10-20 15:06:42

标签: mercurial

我们的.vcproj已修改以修复构建计算机上的问题(变更集1700)。后来,开发人员将他的更改(更改1710到1715)合并到主干中,但mercurial自动合并覆盖了1700的更改。我认为这是因为他选择了错误的分支作为合并的“父”(请参阅​​部分2问题)。

1)解决这个问题的“正确”方法是什么,考虑到所有合并文件,只有一个文件合并错误,

2)开发人员应该采取哪些不同的措施以确保不会发生这种情况?我们有办法实施“正确”的方式吗?

编辑:我可能对发生的事情不够清楚。 Developer A在.vcproj文件中修改了一行,删除了编译器的选项。他的办理登机手续变成了变更集1700.开发人员B,从前一个父母工作(让我们说变更集1690),对项目的完全不同的部分做了一些更改,但他 触摸.vcproj文件(只是没有接近开发人员A所做的更改。当开发人员B合并他的更改(变为1710到1715)时,合并过程会覆盖1700的更改。

为了解决这个问题,我只是重新修改.vcproj文件以再次包含更改,并将其签入。我只是想知道为什么 Mercurial认为它不应该保留更改在1700年,以及是否有“正式”的方法来解决这个问题。

编辑第二个:开发人员B发誓Mercurial合并.vcproj文件而不提示他解决冲突,但当然可能他只是记错了,在这种情况下整个练习都是学术性的。

2 个答案:

答案 0 :(得分:10)

我将首先解决你问题的第二部分......

如果存在冲突,自动合并工具应该强制程序员决定合并的发生方式。但一般的假设是冲突将涉及对同一组线的两次编辑。如果由于对彼此不相近的行的编辑而产生冲突,则自动合并将轻率地选择两个编辑并且将出现错误。

合并工具总是正常合并的一般情况很难解决,而且实际上不能用当前的技术。以下是我对C:

的意思
int i;  // Someone replaces this with 'short i' in one changeset stating
        // that a short is more efficient.

// ...  lots of code;

// Someone else replaces all the 65000s with 100000s in another changeset,
// saying that more precision is needed.
for (i = 0; i < 65000; ++i) {
    integral_approximation_piece(start + i/65000.0, end + (i + 1) / 65000.0);
}

没有合并工具会抓住这种冲突。该工具必须实际编译代码,以查看代码的这两部分与彼此有什么关系,虽然在这种情况下可能就足够了,但我可以构造一个需要运行代码的示例,检查结果以发现冲突。

这意味着您真正应该做的是在合并后严格测试您的代码,就像您应该在任何其他更改之后一样。绝大多数合并将导致开发人员必须解决的明显冲突(即使该解决方案通常相当明显),或者将干净地合并。但是,很少有不适合任何类别的合并都不能轻易地以自动方式处理。

这也可以通过鼓励当地的开发实践来解决。例如,编码标准规定“变量应在其使用的位置附近声明。”

我猜测.vcproj文件特别容易出现这个问题,因为开发人员不太了解它们,所以如果出现冲突,他们就不会确定如何处理它们。我的猜测是,这发生了,你的开发人员只是回复了他签入的修订版。

至于第1部分......

在这种情况下,该怎么做取决于你的开发过程。您可以删除合并变更集并重做它,但如果很多人已经将其拉出来,这将无法正常工作,如果有许多已经检查过的变更集,它将会工作得特别糟糕关于合并变更集。

您还可以签入修复合并问题的新更改。

这些基本上是你的两个选择。

在我看来,你的帖子的语气表明你可能在你的组织中有一些关于这个问题的政治,人们正在将此错误归咎于Mercurial的频繁合并。所以我要指出,任何变更控制系统都可能出现这个问题。例如,在Subversion的情况下,每当开发人员在他们的工作目录中有未完成的更改时进行更新时,他们就会进行合并,并且任何合并都会出现这种问题。

答案 1 :(得分:7)

在mercurial中,合并没有单个父级,根据定义,它只有两个且只有两个父级。当有人合并时,他们会做出两个选择:

  1. 两个变更集将构成两个变更
  2. 其中哪些更改集将是左父项,哪些将是右父项
  3. 在这两个问题中,第一个是非常重要的,第二个问题根本不重要,尽管我花了一些时间才明白这一点。

    使用hg update X选择左父母。这会更改hg parents(或更新版本hg summary)的输出,并基本上确定合并前工作目录中的内容。

    使用hg merge Y选择右父。这表示将X(工作目录的父项)与变更集Y合并。作为一种特殊情况,如果您的存储库中只有两个头,而您的父项已经是其中之一,那么Y将默认为另一个。

    我必须看到你的结果图知道开发人员做了什么,但是在调用merge之前他可能没有更新到一个或另一个头,这会让他在历史记录中合并一个头

    如果您的开发人员选择合适的父母进​​行合并,那么左侧与右侧并不重要 - 唯一真正的区别在于,当使用hg diffhg log -p或其他命令时它显示了合并变更集的修补程序,它相对于左父项显示。然而,这只是显示的一个因素。从功能上讲,它们几乎完全相同。

    假设您的开发人员选择了正确的变更集,那么他应该做的就是在提交之前测试合并的结果。合并软件开发,而不是恼人的VCS副作用,并且在提交之前不进行测试是错误。

    <强>修复

    要解决此问题,只需正确重新进行合并即可。使用hg update设置一个父级,使用hg merge选择另一个父级。确保您当前的工作目录正确,然后提交。你可以使用像hg strip或更好的东西摆脱他的错误合并,只需在更新后用hg commit --close-branch关闭他的分支。

    <强>避免

    你说“mercurial auto-merge”,但mercurial并没有真正自动合并。它做了一个premerge这是一个非常谨慎的明显变化组合,但它是如此小心,如果每个合并父项在同一区域添加代码,它甚至不会为你合并,因为它无法知道哪个代码块你宁愿先拥有。

    您可以使用合并工具配置选项完全或逐个文件地禁用此预合并:

    https://www.mercurial-scm.org/wiki/MergeToolConfiguration?highlight=premerge