2012-02-19 56 views

回答

14

Mercurial 3.0:您现在可以选择祖先用作合并基础。你通过设置merge.preferancestor来做到这一点。当这有意义时,Mercurial会告诉你。下面的例子中,你会看到:懒獾是正确的,你不能选择在命令行使用时通过水银挑选的祖先:

3.0版本之前
$ 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) 

水银。但是,您可以在内部完成,并且为此编写扩展并不难:

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默认使用递归合并策略。

+0

这是一个惊喜!完美的作品。非常感谢你。事实上,我不明白为什么这个功能不包含在Mercurial中。在大多数情况下,人们不需要它,但在必要的情况下,它可以节省数小时的冲突解决,甚至防止不正确的自动合并。我刚刚在回购不正确的更改后遇到这样的问题。 – 2013-03-07 10:12:19

-1

你不能这样做。由于最新的共同的祖先IS真正为您的合并基础

如果你想进行合并,不希望重新考虑(因为你的逻辑基秀/ ME /错误的假设和解决方案的路径),你可以去clone-rebase-merge-export-import修补程序路由

+3

可以有多个“同样好”但不同的候选共享祖先。见http://man.he.net/man1/git-merge-base – 2012-02-19 17:23:15

+0

@LucasMeijer - 1.我们说关于Mercurial,而不是Git 2.他们不是**“同样好”,因为最新的祖先是*“更好”* – 2012-02-19 17:35:11

+2

你有什么理由知道最新的是最好的。伊莫,没有办法知道这一点。 (尽管通常最新的是最好的)。 git链接仅仅说明了没有“最好”的情况,这种情况在mercurial中可能发生的情况也是如此。 – 2012-02-19 18:09:10

1

Base仅用作您的合并工具的另一个输入。如果在合并工具配置中禁用premerge(在没有冲突时,premerge会为您提供“明显选择”),并手动调用合并工具提供您希望作为本地,远程和基础的3个修订版的副本,您可以获得无论你想在你的合并工具。只有左侧父母和右侧父母实际记录在合并中。

+0

是啊,我可以去完全手动路由,并为每个mergeconflict,手动复制粘贴在我想要的基地。尽管如此,我正在考虑20多种合并冲突,并认为我们必须能够自动计算出某些事情。 – 2012-02-19 17:28:07