找到两个分支的最新合并点

23

如果有两个分支,我该如何找到它们合并时最新的修订版本?是否有标准的Mercurial命令可以实现这一点?

这与问题如何在SVN中找到两个分支的共同祖先?相同,只不过是针对Mercurial而不是subversion。


我不明白为什么Lazy Badger的答案是正确的,所以我不得不画了一张小图,现在我明白了:

当两个分支合并时,它们并没有真正地“合并”,而是将一个分支的更改集成到第二个分支中。这意味着合并提交只属于原始分支,而不属于合并后的分支。这就是为什么合并修订版是祖先修订版的两个子节点之一的原因。

这可能最好通过一张图片来说明:

default o----o----a---b---o---o
         \         \
other     `-o---o---m---o

ancestor(default,other) == a
children(ancestor(default,other)) == (b,m)
children(ancestor(default,other)) and merge() == m
7个回答

20
hg log -r "children(ancestor(default, Cleanup)) and merge()" --template "{rev}\n"

最新的合并是为了default和Cleanup分支(Tim Henigan答案的精简版本)。


+1 如果找到了正确的答案!但我不明白为什么我必须使用 children()。 - daniel kullmann
1
祖先(默认,清理)将为您提供最新合并的一个父级(我在开始时使用了Tim的代码)。 您可以在我的存储库http://hg.assembla.com/seeker中查看(我懒得在此处显示glog输出),我用它来进行调试。 我必须找到最新合并的子项(许多可能的子项之一),这是合并。 - Lazy Badger
2
hg help revsets 说:“ancestor(single, single)” 是两个变更集的最近公共祖先。为什么不是合并呢? - daniel kullmann
2
这只是合并的一个父节点,但你问的是最新的合并集,对吧? - Lazy Badger

4

你可以将这个查询重写为:

  • 最接近的单个变更集,它是两个分支末尾的祖先变更集

假设你有两个分支,分别用R1R2来标识,不管是分支的名称、修订号还是每个变更集的哈希值等。

然后你可以通过以下方式找到你要寻找的变更集:

hg log --rev "ancestor(R1,R2)"

4

在Mercurial的最近版本中(>1.7),您可以使用revsets来完成此操作:

hg log -r "max(ancestor(<branch1>, <branch2>))"

相同的revset过滤器也适用于TortoiseHg的过滤器工具栏。


它将是合并集的一个父级,而不是最新的合并集。 - Lazy Badger
2
太棒了!只是需要注意:当分支名称包含连字符 - 等特殊字符时,应该用单引号括起来,例如 hg log -r "max(ancestor('branch-a', 'branch-b'))" - daniel kullmann
1
在函数参数中,最好始终使用引号来表示字符串。 - Lazy Badger

3
如果您有两个以上的分支,则需要向Lazy Badger的答案添加一个额外的过滤器,因为children()可能会给您一些不在您的分支中的子节点。
hg log -r "children(ancestor(default, Cleanup)) and merge() and branch(default|Cleanup)" --template "{rev}\n"

other     o---o-----m1---o
                   /
default   o---o---a---b---o
                   \
another   o---o-----m2---o

ancestor(default, other) == a
children(ancestor(default, other)) == (m1,b,m2)
children(ancestor(default, other)) and merge() == (m1,m2)
children(ancestor(default, other)) and merge() and branch(default, other) == m1

2
您可以使用以下 revset 查询找到从源分支合并到目标分支的所有合并记录:
children(p2(::DESTINATION and merge()) and branch(SOURCE)) and branch(DESTINATION)
  • ::DESTINATION and merge() 获取目标分支中的所有合并。
  • p2(set) 返回每个合并的第二个父级,这始终是被合并到目标分支的源分支上的提交。
  • and branch(SOURCE) 将所有这些合并筛选为只来自源分支的合并。
  • children(set) 返回p2()的所有子级,其中一个是我们正在查找的合并。
  • and branch(DESTINATION)p2()的子级过滤为仅显示目标分支上的提交,正好是我们要查找的合并。

因此,要从源分支获取最新的合并,将上述查询与max(set)查询一起使用。因此最终命令将是:

max(children(p2(::DESTINATION and merge()) and branch(SOURCE)) and branch(DESTINATION))

1

仅供后人参考,如果左分支尚未与右分支合并,那么这种做法是不正确的,但是左分支最近已经合并到了右分支中。

正确的解决方案是:

last(parents((ancestors('{left_branch}') and branch('{left_branch}') and merge())) and branch({right_branch}))

0
hg log -r "last(ancestors(target) & branch(source))"

这将给您目标分支分支上的最近公共祖先。

source         o---a---o---m2---o
                    \      /
intermediate   o--o--m1---b---o
                               \
target         o---o------------m3---o

在这个例子中,源分支和目标分支的最近公共祖先是b,但是b不在源分支上,因此我们想要得到a
要得到b,您可以使用Lasse的解决方案:
hg log -r "ancestor(source, target)"

我经常想知道某个任务分支中最新的“默认”修订版本,而且我不在乎我的任务分支是直接与默认分支合并还是通过某些中间路径合并。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接