Mercurial 和合并工具?
当正在合并的两个分支对同一文件进行更改时,Mercurial 是否始终使用外部合并工具?
或者它是否首先查看是否可以合并文件本身,如果不能,则仅使用外部工具?
我问这个问题的原因是我(再次)重新阅读 Joel Spolsky 在 Mercurial 上编写的教程 在比较 Subversion 和 Mercurial 的合并方式时,他说的一件事是:
相比之下,当我们在 Mercurial 中单独工作时,Mercurial 正忙于维护一系列变更集。因此,当我们想要将代码合并在一起时,Mercurial 实际上拥有更多信息:它知道我们每个人更改了什么,并且可以重新应用这些更改,而不是仅仅查看最终产品并尝试猜测如何放置它一起。
只是,我的经验告诉我,当两个分支对同一文件进行更改时,似乎涉及外部合并工具。那么,这是否会导致上述论点不正确呢?
或者我应该将其解释如下:
- Subversion 只合并两个分支的最终状态,并且在一个单元中还有更多的工作要做
- Mercurial 单独合并每个变更集,这使得它能够处理较小的变更单元,并且有更高的机会合并成功
有人可以解释一下吗?
编辑:让我举个例子:
@echo off
setlocal
if exist repo rd /s /q repo
md repo
cd repo
hg init .
rem --- version 0 ---
echo 1 >test.txt
echo 2 >>test.txt
echo 3 >>test.txt
echo 4 >>test.txt
echo 5 >>test.txt
hg add test.txt
hg commit -m "v0"
rem --- version 1 ---
echo 1 >test.txt
echo 2 v1 >>test.txt
echo 3 >>test.txt
echo 4 >>test.txt
echo 5 >>test.txt
hg commit -m "v1"
rem --- version 2 ---
hg update 0
echo 1 >test.txt
echo 2 >>test.txt
echo 3 >>test.txt
echo 4 v2 >>test.txt
echo 5 >>test.txt
hg commit -m "v2"
rem --- merge ---
hg update 1
hg merge 2
首先创建一个包含以下内容的文件:
1
2
3
4
5
然后将其更改为:
1
2 v1
3
4
5
然后返回到初始版本(变更集),并将其更改为:
1
2
3
4 v2
5
然后它尝试将两者合并。
现在,根据(当前)单一答案,这应该不会造成问题,因为更改并不冲突。
然而,此时,Beyond Compare(我的外部合并工具)被调用。
Is Mercurial always using the external merge tools when two branches that are merging have changes to the same file?
Or does it first see if it can merge the file itself, and only punting to the external tool if it can't?
The reason I'm asking is that I am (once again) re-reading the tutorial written by Joel Spolsky on Mercurial and one thing he says, when comparing how Subversion and Mercurial is merging is that:
By contrast, while we were working separately in Mercurial, Mercurial was busy keeping a series of changesets. And so, when we want to merge our code together, Mercurial actually has a whole lot more information: it knows what each of us changed and can reapply those changes, rather than just looking at the final product and trying to guess how to put it together.
Only, my experience tells me that it seems to involve the external merge tool when two branches have changes to the same files. And thus, doesn't that render the above argument incorrect?
Or should I interpret this as follows:
- Subversion only merges the final state of the two branches, and has more work to do in a single unit
- Mercurial merges each changeset individually, which allows it to work with smaller units of changes, with higher chance of merge success
Can someone shed some light on this?
Edit: Let me give an example:
@echo off
setlocal
if exist repo rd /s /q repo
md repo
cd repo
hg init .
rem --- version 0 ---
echo 1 >test.txt
echo 2 >>test.txt
echo 3 >>test.txt
echo 4 >>test.txt
echo 5 >>test.txt
hg add test.txt
hg commit -m "v0"
rem --- version 1 ---
echo 1 >test.txt
echo 2 v1 >>test.txt
echo 3 >>test.txt
echo 4 >>test.txt
echo 5 >>test.txt
hg commit -m "v1"
rem --- version 2 ---
hg update 0
echo 1 >test.txt
echo 2 >>test.txt
echo 3 >>test.txt
echo 4 v2 >>test.txt
echo 5 >>test.txt
hg commit -m "v2"
rem --- merge ---
hg update 1
hg merge 2
This first creates a file with the following content:
1
2
3
4
5
Then it changes it to:
1
2 v1
3
4
5
Then it goes back to the initial version (changeset), and changes it to:
1
2
3
4 v2
5
Then it attempts to merge the two.
Now, according to the (currently) single answer, this should not pose a problem, since the changes are not in conflict.
However, at this point, Beyond Compare (my external merge tool) is invoked.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Mercurial 合并和 svn 合并之间的最大区别在于,mercurial 合并算法可以访问正在合并的两个修订版本之间的最后一个共同祖先。如果你的历史记录看起来像
svn 会让你的合并工具在 B 和 C 上失败。Mercurial 会用 A、B 和 C 启动你的工具,有些工具在这方面做得更好。
Mercurial 在启动工具之前确实会进行自己的内部合并,其中它使用 A、B 和 C 来自行做出一些明显的选择。您可以通过更改工具的
预合并
设置来关闭它。您的测试没有给出很好的结果,因为您正在将 2 与其自己的祖先合并。相反,如果您在创建变更集 2 之前执行
hg update 0
,那么您就有这样的实际分支历史记录:那么当您
hg merge
时,您将得到:没有合并工具启动。
The big difference between mercurial merging and svn merging is that the mercurial merge algorithm has access to the last-common-ancestor between the two revisions being merged. If your history looks like
svn will turn your merge tools lose on B and C. Mercurial will launch your tool with A, B, and C and some tools do better stuff with that.
Mercurial does do its own internal merge before launching your tool where it uses A, B, and C to make some of the obvious choices itself. You can turn that off by altering the
premerge
setting for a tool.Your test isn't giving great results because you're merging 2 with its own ancestor. If instead you do a
hg update 0
before creating changeset 2, so you have an actual branching history like this:then when you
hg merge
you'll get:without your merge tool launching.
仅当存在需要解决的冲突时才会调用合并工具。在不同分支中对同一文件的更改构成了此类冲突。
除此之外,实际的合并算法不是基于变更集的,而是基于文件的,以实现最佳合并结果。有关更多详细信息,请参阅 Mercurial Wiki。
Mercurial 会让您的合并保持未提交状态,因此您有机会在提交合并变更集之前检查您的代码。
The mergetool is invoked only in case there's a conflict that needs to be resolved. Changes to the same file in different branches constitutes such a conflict.
Other than that, the actual merge algorithm isn't changeset based, it's file based to allow for best merge results. See the Mercurial Wiki for more details.
Mercurial leaves your merge uncomitted, so you have a chance to check your code before comitting the merge changeset.