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

mos*_*ald 10 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文件而没有提示他解决冲突,但当然可能他只是记错了,在这种情况下,整个练习都是学术性的.

Omn*_*ous 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

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

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

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

  • +1因为关于合并的最重要的事情之一是它们与任何代码更改提交一样严重.只有工具使它们变得更容易这一事实并不意味着开发人员不需要关心它们. (5认同)
  • 嗯.我不认为我有任何"语气".我碰巧喜欢Mercurial(和我的团队一样),我想知道是否有一种修复错误的"Mercurial方式". (3认同)

Ry4*_*ase 7

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

  1. 这两个变化将构成两个变化
  2. 哪些变更集将是左父项,哪些将是右父项

在这两个问题中,第一个是非常重要的,第二个问题根本不重要,尽管我花了一些时间才明白这一点.

您可以使用选择左侧父级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