如何指定在“hg merge”中使用的合并基?

发布于 2025-01-07 05:24:23 字数 126 浏览 0 评论 0原文

我正在尝试在复杂的 hg 存储库中进行复杂的合并。我对 Mercurial 选择用作执行合并的“基础”的“最新共享祖先”并不满意。

我想指定我自己选择的特定提交作为基础。

这可能吗?如果可能的话,如何实现?

I'm trying to do a complicated merge in a complicated hg repository. I'm not happy with the "newest shared ancestor" that Mercurial chooses to use as the "base" to perform the merge.

I'd like to specify a specific commit of my own choice to use as base.

Is this possible, and if so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一人独醉 2025-01-14 05:24:23

Mercurial 3.0:您现在可以选择祖先作为合并基础。您可以通过设置merge.preferancestor来做到这一点。当这有意义时,Mercurial 会告诉您。通过下面的示例,您将看到:

$ hg merge
note: using eb49ad46fd72 as ancestor of 333411d2f751 and 7d1f71140c74
      alternatively, use --config merge.preferancestor=fdf4b78f5292
merging x
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Mercurial 3.0 版之前: Lazy Badger 是正确的,您在从命令行使用 Mercurial 时无法选择 Mercurial 所选择的祖先。但是,您可以在内部完成此操作,并且为此编写扩展并不太困难:

from mercurial import extensions, commands, scmutil
from mercurial import merge as mergemod

saved_ancestor = None

def update(orig, repo, node, branchmerge, force, partial, ancestor=None):
    if saved_ancestor:
        ancestor = scmutil.revsingle(repo, saved_ancestor).node()
    return orig(repo, node, branchmerge, force, partial, ancestor)

def merge(orig, ui, repo, node=None, **opts):
    global saved_ancestor
    saved_ancestor = opts.get('ancestor')
    return orig(ui, repo, node, **opts)

def extsetup(ui):
    extensions.wrapfunction(mergemod, 'update', update)
    entry = extensions.wrapcommand(commands.table, 'merge', merge)
    entry[1].append(('', 'ancestor', '', 'override ancestor', 'REV'))

将其放入文件中并加载扩展。您现在可以用来

hg merge --ancestor X

覆盖正常的祖先。正如您所发现的,如果有多个可能的祖先,这确实会产生影响。如果进行交叉合并,就会出现这种情况。您可以使用以下命令创建这样的情况:

hg init; echo a > x; hg commit -A -m a x
hg update 0; echo b >> x; hg commit -m b
hg update 0; echo c >> x; hg commit -m c
hg update 1; hg merge --tool internal:local 2; echo c >> x; hg commit -m bc
hg update 2; hg merge --tool internal:local 1; echo b >> x; hg commit -m cb

该图如下所示:

@    changeset: 4:333411d2f751
|\
+---o  changeset: 3:7d1f71140c74
| |/
| o  changeset: 2:fdf4b78f5292
| |
o |  changeset: 1:eb49ad46fd72
|/
o  changeset: 0:e72ddea4d238

如果您正常合并,您将获得变更集 eb49ad46fd72 作为祖先,并且文件 x 包含:

a
c
b
c

如果您改为使用 hg merge --ancestor 2 您会得到不同的结果:

a
b
c
b

在这两种情况下,我的 KDiff3 都能够自动处理合并,而不会报告任何冲突。如果我使用“递归”合并策略并选择 e72ddea4d238 作为祖先,那么我会遇到明显的冲突。 Git 默认使用递归合并策略。

Mercurial 3.0: You can now select the ancestor to use as a merge base. You do that by setting merge.preferancestor. Mercurial will tell you about it when this makes sense. With the example below, you would see:

$ hg merge
note: using eb49ad46fd72 as ancestor of 333411d2f751 and 7d1f71140c74
      alternatively, use --config merge.preferancestor=fdf4b78f5292
merging x
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Mercurial before version 3.0: Lazy Badger is correct that you cannot pick the ancestor picked by Mercurial when using it from the command line. However, you can do it internally and it's not too difficult to write an extension for this:

from mercurial import extensions, commands, scmutil
from mercurial import merge as mergemod

saved_ancestor = None

def update(orig, repo, node, branchmerge, force, partial, ancestor=None):
    if saved_ancestor:
        ancestor = scmutil.revsingle(repo, saved_ancestor).node()
    return orig(repo, node, branchmerge, force, partial, ancestor)

def merge(orig, ui, repo, node=None, **opts):
    global saved_ancestor
    saved_ancestor = opts.get('ancestor')
    return orig(ui, repo, node, **opts)

def extsetup(ui):
    extensions.wrapfunction(mergemod, 'update', update)
    entry = extensions.wrapcommand(commands.table, 'merge', merge)
    entry[1].append(('', 'ancestor', '', 'override ancestor', 'REV'))

Put this in a file and load the extension. You can now use

hg merge --ancestor X

to override the normal ancestor. As you've found out, this does make a difference if there are several possible ancestors. That situation arises if you have criss-cross merges. You can create such a case with these commands:

hg init; echo a > x; hg commit -A -m a x
hg update 0; echo b >> x; hg commit -m b
hg update 0; echo c >> x; hg commit -m c
hg update 1; hg merge --tool internal:local 2; echo c >> x; hg commit -m bc
hg update 2; hg merge --tool internal:local 1; echo b >> x; hg commit -m cb

The graph looks like this:

@    changeset: 4:333411d2f751
|\
+---o  changeset: 3:7d1f71140c74
| |/
| o  changeset: 2:fdf4b78f5292
| |
o |  changeset: 1:eb49ad46fd72
|/
o  changeset: 0:e72ddea4d238

If you merge normally you get changeset eb49ad46fd72 as the ancestor and the file x contains:

a
c
b
c

If you instead use hg merge --ancestor 2 you get a different result:

a
b
c
b

In both cases, my KDiff3 were able to handle the merge automatically without reporting any conflicts. If I use the "recursive" merge strategy and pick e72ddea4d238 as the ancestor, then I'm presented with a sensible conflict. Git uses the recursive merge strategy by default.

若言繁花未落 2025-01-14 05:24:23

Base 只是用作合并工具的另一个输入。如果您在合并工具配置中禁用 premerge (当不存在冲突时,premerge 会为您做出“明显的选择”)并手动调用合并工具,提供您想要作为本地、远程版本的 3 个修订版本的副本和基础,您可以在合并工具中获得您想要的任何内容。合并中实际上只记录左父项和右父项。

Base is just used as another input to your merge tool. If you disable premerge in your Merge Tool Configuration (premerge makes the "obvious choices" for you when there are no conflicts) and invoke your merge tool manually providing copies of the 3 revisions you want as local, remote, and base, you can get whatever you want in your merge tool. Only the left parent and right parent are actually recorded in the merge.

变身佩奇 2025-01-14 05:24:23

你做不到。因为最新的共享祖先合并的真正基础

如果您想执行合并并且不想重新思考(因为您的逻辑基础显示/me/错误的假设和解决方案路径),您可以走克隆-变基-合并-导出-导入补丁路线

You can't do it. Because newest shared ancestor IS real base for your merge

If you want to perform merge and don't want re-think (because your logic-base show /me/ wrong assumptions and solution-path) you can go clone-rebase-merge-export-import patch route

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文