如何正确关闭 Mercurial 中的功能分支?

Posted

技术标签:

【中文标题】如何正确关闭 Mercurial 中的功能分支?【英文标题】:How to correctly close a feature branch in Mercurial? 【发布时间】:2011-01-15 06:50:40 【问题描述】:

我已经完成了功能分支feature-x 的工作。我想将结果合并回default 分支并关闭feature-x,以便在hg branches 的输出中摆脱它。

我想出了以下场景,但它有一些问题:

$ hg up default
$ hg merge feature-x
$ hg ci -m merge
$ hg up feature-x
$ hg ci -m 'Closed branch feature-x' --close-branch

所以 feature-x 分支 (changests 40-41) 已关闭,但有一个新头,即将关闭的分支变更集 44,将列在 @ 987654331@每次:

$ hg log ...
o  44 Closed branch feature-x
|
| @  43 merge
|/|
| o  42 Changeset C
| |
o |  41 Changeset 2
| |
o |  40 Changeset 1
|/
o  39 Changeset B
|
o  38 Changeset A
|

更新:从 1.5 版开始,Mercurial 似乎不再在 hg heads 的输出中显示封闭分支的头部。

是否可以关闭合并的分支而不留下一个头?有没有更正确的方法来关闭特性分支?

相关问题:

Is there a downside to this Mercurial workflow: named branch "dead" head?

【问题讨论】:

@Andrey:但指出的文章不仅仅谈论“--close-branch”。它显示了修剪分支的 四种 方法。如果您真的不再想要它,您可以按照文章中的说明进行克隆。唯一的“问题”是您是否出于某种原因想要关闭它,但仍保留它。 @WizardOfOdds 是的,我已经阅读了整篇关于修剪枯枝的文章。我希望分支保留在修订历史中,而不是丢弃它。以前我只是将功能分支合并到default 中,而没有“关闭”它们。它产生了 0 个新头,但这些分支在 hg branches 中永远可见(作为非活动分支)。 为了开发功能,我倾向于克隆整个存储库,然后在功能完成后将其合并回来。我不喜欢历史上(关闭)分支的遗骸。 【参考方案1】:

一种方法是让合并的功能分支保持打开(和非活动状态):

$ hg up default
$ hg merge feature-x
$ hg ci -m merge

$ hg heads
    (1 head)

$ hg branches
default    43:...
feature-x  41:...
    (2 branches)

$ hg branches -a
default    43:...
    (1 branch)

另一种方法是在合并之前使用额外的提交关闭功能分支:

$ hg up feature-x
$ hg ci -m 'Closed branch feature-x' --close-branch
$ hg up default
$ hg merge feature-x
$ hg ci -m merge

$ hg heads
    (1 head)

$ hg branches
default    43:...
    (1 branch)

第一个更简单,但它留下了一个开放的分支。第二个没有留下开放的头/分支,但它需要一个额外的辅助提交。可以使用--close-branch 将对功能分支的最后一次实际提交与这个额外提交结合起来,但应该提前知道哪个提交将是最后一个。

更新:从 Mercurial 1.5 开始,您可以随时关闭分支,因此它不会再出现在 hg brancheshg heads 中。唯一可能让您烦恼的是,从技术上讲,修订图仍然会有一个没有子项的修订。

更新 2:自 Mercurial 1.8 以来,书签已成为 Mercurial 的核心功能。书签比命名分支更便于分支。另请参阅此问题:

Mercurial branching and bookmarks

【讨论】:

Bookmarks are more convenient for branching than named branches 不一定是真的。 Hg 书签与 Git 分支不同。它们充满了许多边缘情况,这使得它们不适合作为特征分支。例如:当您克隆存储库时,您最终会在 default 分支中获得最新提交。如果您使用书签,则此变更集对应于随机(不稳定)书签。如果您使用命名分支,您将在稳定/默认分支中获得最新提交,这通常是您想要的。书签总有一天会到达那里,但它们还没有到达那里。 我将书签用作仅在本地存储库中可见的私有标签。它们提醒我需要重新访问的变更集。 我尝试采用这种方法,但尝试推送时仍然出现错误:abort: push creates new remote branches:。我做错了什么?【参考方案2】:

恕我直言,忘记关闭的分支机构有两种情况

案例 1: 分支没有合并到默认中

在这种情况下,我更新到分支并使用 --close-branch 进行另一次提交,不幸的是,这会选择分支成为新提示,因此在将其推送到其他克隆之前,我确保真正的提示收到更多更改和其他人不会对这个奇怪的提示感到困惑。

hg up myBranch
hg commit --close-branch

案例 2: 分支被合并到默认中

这个案例与案例 1 没有太大区别,可以通过复制案例 1 的步骤和另外两个步骤来解决。

在这种情况下,我更新到分支变更集,使用 --close-branch 进行另一次提交,并将成为提示的新变更集合并为默认值。最后一个操作在默认分支中创建了一个新提示 - HOORAY!

hg up myBranch
hg commit --close-branch
hg up default
hg merge myBranch

希望这对未来的读者有所帮助。

【讨论】:

对于像我这样的 Mercurial 新手来说,这是一个很好的明确答案。并感谢您不使用 hg help 未将其列为命令之一的“ci”,所以我不知道它是什么意思 :) @MB.: 在这种情况下,hg help ci 会为您解释。 我相信'hg merge'命令会告诉你,最后还有另一个提交【参考方案3】:

编辑哎呀,太晚了...我知道阅读了您的评论,指出您希望保留 feature-x 变更集,因此这里的克隆方法不起作用。

我仍然会在这里给出答案,因为它可能对其他人有所帮助。

如果您想完全摆脱“功能 X”,例如因为它不起作用,您可以克隆。这是文章中解释的方法之一,它确实有效,并且专门讨论了头部。

据我了解,您有这个并且想一劳永逸地摆脱“feature-x”头:

@    changeset:   7:00a7f69c8335
|\   tag:         tip
| |  parent:      4:31b6f976956b
| |  parent:      2:0a834fa43688
| |  summary:     merge
| |
| | o  changeset:   5:013a3e954cfd
| |/   summary:     Closed branch feature-x
| |
| o  changeset:   4:31b6f976956b
| |  summary:     Changeset2
| |
| o  changeset:   3:5cb34be9e777
| |  parent:      1:1cc843e7f4b5
| |  summary:     Changeset 1
| |
o |  changeset:   2:0a834fa43688
|/   summary:     Changeset C
|
o  changeset:   1:1cc843e7f4b5
|  summary:     Changeset B
|
o  changeset:   0:a9afb25eaede
   summary:     Changeset A

所以你这样做:

hg clone . ../cleanedrepo --rev 7

您将拥有以下内容,并且您会看到 feature-x 确实消失了:

@    changeset:   5:00a7f69c8335
|\   tag:         tip
| |  parent:      4:31b6f976956b
| |  parent:      2:0a834fa43688
| |  summary:     merge
| |
| o  changeset:   4:31b6f976956b
| |  summary:     Changeset2
| |
| o  changeset:   3:5cb34be9e777
| |  parent:      1:1cc843e7f4b5
| |  summary:     Changeset 1
| |
o |  changeset:   2:0a834fa43688
|/   summary:     Changeset C
|
o  changeset:   1:1cc843e7f4b5
|  summary:     Changeset B
|
o  changeset:   0:a9afb25eaede
   summary:     Changeset A

我可能误解了您想要的内容,但请不要修改,我花时间重现了您的用例:)

【讨论】:

【参考方案4】:

奇怪的是,还没有人提出关闭功能分支的最强大的方法...... 您只需 combine 将提交与 --close-branch 标志合并(即提交修改后的文件并同时关闭分支):

hg up feature-x
hg merge default
hg ci -m "Merge feature-x and close branch" --close-branch
hg branch default -f

所以,仅此而已。转速图上没有多余的人头。没有额外的提交。

【讨论】:

我在我的回答中提到过:“”“可以使用 --close-branch 将最后一次实际提交到功能分支与这个额外的提交结合起来,但是应该提前知道哪个提交将是最后一个。""" 好的,我明白了。我只是不太明白句子的最后一部分(“但是应该知道……”),所以我认为它的含义有所不同。另外我想指出,大多数 GUI 工具(TortoiseHG、SourceTree 等)都不支持这种方法。 @AndreyVlasovskikh 这个答案的重点是在合并中关闭分支,而不是在功能分支的最后一次提交中关闭。 @tav 在发出merge 命令之前,最好使用hg branch 来验证合并的分支名称是否是您想要保持打开的分支名称。 仔细观察,合并似乎总是在关闭的分支上。期望的结果将是在其父母之一的分支上并关闭其另一父母的分支。这似乎是不可能的。所以这看起来毕竟不是一个可行的解决方案。太糟糕了,我真的很想使用合并作为分支的结束点。

以上是关于如何正确关闭 Mercurial 中的功能分支?的主要内容,如果未能解决你的问题,请参考以下文章

Mercurial:在一个仓库中的分支之间合并一个文件

在推送之前丢弃 Mercurial 中的本地分支

如何在 Mercurial 中重复合并分支

如何在 Mercurial 中克隆存储库的子文件夹?

Mercurial - 如何重新启动分支[重复]

Subversion:如何获取所有活动的,未合并的分支的列表