Mercurial:分支特定的更改在虚拟合并后不断返回

时间:2012-03-02 11:51:25

标签: mercurial merge

我有一个mercurial存储库,有两个永久分支,默认和UAT。每隔一段时间,我们就会将新版本的应用程序部署(推广)到UAT环境中,我们通过将稳定的默认提交合并到UAT分支来实现。偶尔会在UAT分支中修复错误,这些错误修复会合并回默认值。

在UAT分支上,我需要为部署目的更改一些内容 - 连接字符串和各种环境设置。我试图做的是在UAT分支中进行这些更改并在将默认值合并到UAT之后立即提交它们(全部作为一个提交)。然后我将这一个提交虚拟合并到默认值 - 想法是因为默认现在在它的祖先中有这个提交将来错误修复从UAT合并到默认值将不会尝试重做这些特定于UAT的更改。

然而事情并没有像我希望的那样顺利。从虚拟合并提交开始到默认情况,我尝试了以下两种情况:

1) Make a few more commits to default and then "promote" to UAT (merge default onto UAT)
2) Make a bugfix on UAT and "backport" it to default (merge UAT onto default)

在跑步#1和#2之间,我已将所有内容都删除,以便两个场景都从同一点开始。

我所看到的是,根据合并的最后一个方向,我仍然需要在执行一个或另一个合并并恢复之后检查更改的文件 - 有时合并会尝试将默认配置放入UAT,有时甚至是UAT配置合并。

如果我恢复配置更改并提交合并,那么将来在同一方向上的合并行为正常,但是当我走向另一个方向时,合并会再次将错误的配置放入文件中。

我错过了什么?

1 个答案:

答案 0 :(得分:5)

我认为问题类似于this question中的问题:合并不会像您认为的那样有效。合并只是比较文件状态的问题,是将更改从一个分支应用到另一个分支的问题。

你的出发点是这样的历史:

UAT:      ... x --- y --- z
                           \
default:  ..... a --- b --- c

其中xy包含UAT的配置设置,而b是没有配置设置的虚拟合并。因此,b中的文件与a中的文件类似 - 它们是虚拟合并的。

如果您现在对要升级为UAT的default进行新的更改,则可以使用:

UAT:      ... x --- y 
                     \
default:  ..... a --- b --- c

合并介于yc之间。这是一个简并合并,共同的祖先是y本身。这意味着bc之间的所有更改都将在三向合并中“赢”。关于帅哥如何在三方合并中合并的表格是:

ancestor  local  other -> merge
old       old    old      old (nobody changed the hunk)
old       old    new      new (they changed the hunk)
old       new    old      new (you changed the hunk)
old       new    new      new (hunk was cherry picked onto both branches)
old       foo    bar      <!> (conflict, both changed hunk but differently)

请注意,合并结果不依赖于合并的“方向”:该表关于localother列是对称的。此处,ancestorlocal均为yotherc。因此表格变为:

ancestor  local  other -> merge
old       old    new      new (they changed the hunk)

您可以看到合并结果始终包含new中的c更改。

合并退化并不重要。假设你在UAT上有一个新的提交,并且这个提交没有触及配置字符串,那么你在合并时会得到相同的行为(在任一方向上,合并都是对称的)。

此问题的正常解决方案是外部化配置字符串。把它们放在版本控制之外的地方 - 环境变量,无版本的配置文件等等。如果可以,那么将版本控制下的配置文件作为模板。然后,为UAT分支创建一个无版本的配置文件,其中包含受版本控制的配置文件。您可以根据需要覆盖此无版本配置文件中的设置。