为什么一个分支中的Mercurial退出会影响其他分支?

Jam*_*ice 15 version-control mercurial branch dvcs three-way-merge

这是一个难以解释的情况,所以请耐心等待.我有一个Mercurial存储库,有2个主要分支,默认开发.

工作通常在dev(特征分支)的命名分支中完成.任何时候都可能有许多功能分支.一旦在该分支中完成工作,它就会合并回dev.

当准备发布时,另一个命名分支是从dev(发布分支)创建的.有时需要从发布中排除整个功能.如果是这种情况,则将功能分支合并到dev中的合并更改集从新版本分支中退出.

一旦发布分支准备好发布,它就会合并为默认值(因此默认情况下始终代表生产中代码的状态).在dev分支和功能分支上正常工作.

当需要执行另一个版本时,会出现问题,包括在先前版本中退出的功能.正常创建新的发布分支(脱离开发).此新版本分支现在包含从先前版本分支退出的功能(因为退出是在发布分支上执行的,并且合并更改集仍保留在dev分支上).

这次,当发布分支准备好发布并合并为默认值时,由于先前版本分支中的合并回退而退出的任何更改都不会合并为默认值.为什么会这样?由于新版本分支包含所有功能分支变更集(没有任何内容被撤消),为什么默认分支也不会收到所有这些变更集?

如果以上所有内容都难以理解,这里是TortoiseHg的截图,显示了基本问题."branch1"和"branch2"是功能分支,"release"和"release2"是发布分支:

在此输入图像描述

Mar*_*ler 26

我认为问题在于合并的工作方式与您的想法不同.你写

由于新版本分支包含所有功能分支变更集(没有任何内容被撤消),为什么默认分支也不会收到所有这些变更集?

当您合并两个分支时,将其视为将所有更改从一个分支应用到另一个分支是错误的.因此,default分支机构不会"接收"任何变更集release2.我知道这是我们通常认为合并的方式,但这是不准确的.

合并两个变更集时实际发生的情况如下:

  1. Mercurial找到了两个变更集的共同祖先.

  2. 对于两个变更集之间不同的每个文件,Mercurial 使用祖先文件,第一个变更集中的文件和第二个变更集中的文件运行三向合并算法.

在您的情况下,您正在合并修订版本11和12.最不常见的祖先是修订版8.这意味着Mercurial将在修订版本的文件之间运行三向合并:

  • 修订版8:没有退出

  • 修订版11:功能分支已退出

  • 修订版12:没有退出

在三方合并中,变革总是胜过没有变化.Mercurial发现文件已经在8到11之间进行了更改,并且它在8到12之间没有变化.因此它在合并中使用了修订版11中的更改​​版本.这适用于任何三向合并算法.完全合并表看起来是这样的地方old,new......是匹配的三个文件帅哥的内容:

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)
Run Code Online (Sandbox Code Playgroud)

由于这种令人惊讶的合并行为,我担心不应该退出合并变更集.如果您尝试退出合并,Mercurial 2.0及更高版本将中止并投诉.

一般来说,可以说三向合并算法假设所有变化都是好的.因此,如果您合并branch1dev后来使用退出撤消合并,那么合并算法将认为状态比以前"更好".这意味着,你不能只是重新合并branch1dev在以后得到支持出更改回.

您可以做的是在合并时使用"虚拟合并" default.您只需合并并始终保持您正在合并的发布分支中的更改default:

$ hg update default
$ hg merge release2 --tool internal:other -y
$ hg revert --all --rev release2
$ hg commit -m "Release 2 is the new default"
Run Code Online (Sandbox Code Playgroud)

这将解决问题和力量default就像release2.这假定在default未合并到发布分支的情况下绝对不会进行任何更改.

如果您必须能够使用跳过的功能进行发布,那么"正确"的方法是根本不合并这些功能.合并是一个坚定的承诺:你告诉Mercurial合并变更集现在拥有来自其祖先的所有好东西.只要Mercurial不会让你在合并时选择自己的基本版本,三向合并算法就不会让你改变主意退出.

但是,你可以做的是退出退出.这意味着您将更改从功能分支重新引入发布分支.所以你从一个图表开始

release: ... o --- o --- m1 --- m2
                        /      /
feature-A:   ... o --- o      /
                             /
feature-B:  ... o --- o --- o 
Run Code Online (Sandbox Code Playgroud)

您现在确定A功能很糟糕并且您退出合并:

release: ... o --- o --- m1 --- m2 --- b1
                        /      /
feature-A:   ... o --- o      /
                             /
feature-B:  ... o --- o --- o 
Run Code Online (Sandbox Code Playgroud)

然后,将另一个功能合并到发布分支中:

release: ... o --- o --- m1 --- m2 --- b1 --- m3
                        /      /             /
feature-A:   ... o --- o      /             /
                             /             /
feature-B:  ... o --- o --- o             /
                                         /
feature-C:  ... o --- o --- o --- o --- o 
Run Code Online (Sandbox Code Playgroud)

如果您现在想要重新引入A功能,那么您可以退出b1:

release: ... o --- o --- m1 --- m2 --- b1 --- m3 --- b2
                        /      /             /
feature-A:   ... o --- o      /             /
                             /             /
feature-B:  ... o --- o --- o             /
                                         /
feature-C:  ... o --- o --- o --- o --- o 
Run Code Online (Sandbox Code Playgroud)

我们可以将增量添加到图表中,以更好地显示何时何地发生变化:

                     +A     +B     -A     +C     --A
release: ... o --- o --- m1 --- m2 --- b1 --- m3 --- b2
Run Code Online (Sandbox Code Playgroud)

在第二次退出之后,您可以再次合并feature-A以防万一在那里添加了新的变更集.您正在合并的图表如下所示:

release: ... o --- o --- m1 --- m2 --- b1 --- m3 --- b2
                        /      /             /
feature-A:   ... o -- a1 - a2 /             /
                             /             /
feature-B:  ... o --- o --- o             /
                                         /
feature-C:  ... o --- o --- o --- o --- o 
Run Code Online (Sandbox Code Playgroud)

你合并a2b2.共同的祖先将是a1.这意味着,只有你需要在三方合并考虑的其它改革之间a1以及a2a1b2.这里b2已经有大量的更改"in",a2因此合并将很小.