为什么Mercurial不需要“递归合并策略”?

发布于 2024-11-04 11:42:53 字数 183 浏览 7 评论 0原文

AFAIK git 的默认合并策略是“递归”,这意味着当多个“共同祖先”最终成为“好的候选者”时,git 会将它们合并并为贡献者创建一个新的“虚拟共同祖先”。它基本上有助于解决文件已经合并的情况,并避免再次合并它们或出现不正确的合并贡献者。

我的问题是:如果Mercurial不使用“递归”,它如何处理同样的情况?

谢谢

AFAIK git's default merge strategy is "recursive" which means when more than one "common ancestor" ends up being a "good candidate", git will merge them and create a new "virtual common ancestor" for the contributors. It basically helps solving situations where files were already merged and it avoids merging them again or coming up with incorrect merge contributors.

My question is: if Mercurial doesn't use "recursive", how does it handle the same situation?

Thanks

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

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

发布评论

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

评论(2

吾性傲以野 2024-11-11 11:42:53

大多数版本控制系统不知道如何处理有多个基础版本可供合并的情况。数学合并方程为

Result = Destination + SumOf(I=1-N)(Base(I) - Source(I))

在大多数情况下 N=1,您会得到与源的经典合并,典型的三向合并工具可以处理的目标版本和基本版本。尽管许多源代码控制系统甚至在这种简单的情况下也没有用于查找基本版本的正确算法。为此,您需要沿着合并箭头向上追溯版本树,直到遇到共同的祖先。但有时共同祖先太远,不适合上面的等式 N=1,在这种情况下,您需要为多个部分合并找到多个共同祖先。

示例是一个分支被向下和向上合并多次的情况,然后我们尝试将更改从该分支交叉合并到另一个分支。在这种情况下,N>1。 1,但低于源分支上的合并次数。

这是分支合并中最难做的事情之一,我不知道有哪个源代码控制系统能够真正正确地做到这一点。

Most version control system do not know how to handle a situation where there is multiple base versions for a merge. The math merge equation is

Result = Destination + SumOf(I=1-N)(Base(I) - Source(I))

In most cases N=1 and you got a classic merge with source, destination and base versions which a typical 3-way merge tool can handle. Although many source control systems do not have even in this simple case a correct algorithm for finding the Base version. To do so you need to trace back through version tree going up the merge arrows, until you meet at a common ancestor. But sometimes the common ancestor is too far, not fitting the equation above for N=1 and in that case you need to find multiple common ancestors for multiple partial merges.

Example would be a case where a branch is merged down and up multiple times, then we try to cross merge the changes from this branch to another branch. In such case the N > 1, but lower than the number of merge downs on the source branch.

This is one of the hardest thing to do in branch merging and I don't know a source control system that actually does it correctly.

相守太难 2024-11-11 11:42:53

Mercurial 的原作者写了为什么他不使用递归合并策略(链接):基本上答案是:

对于祖先模糊性是最有趣的情况,递归合并根本没有帮助。所以我认为他们不值得额外的复杂性

但是完整的 答案读起来真的很有趣,所以我鼓励你这样做。我将其复制到这里以防它消失:

> Does Mercurial supports recursive merge strategy like git? It is used
> in situation when
> merge has two "common" ancestors (also know as criss-cross merge)
> 
> According to http://codicesoftware.blogspot.com/2011/09/merge-recursive-strategy.html
> Mercurial
> does not support it but I wanted to ask to make sure that nothing has changed.

Indeed. But you shouldn't judge the situation from this blog post as
it's not coherent.

In particular, the example given under "Why merge recursive is better –
a step by step example" doesn't appear to be a recursive merge situation
at all! Notice the key difference in topology as compared with the
initial diagrams: no criss-crossing merges leading up to the merge. Some
kind of bait and switch happening here.

In the example itself, Git will choose the same (single) ancestor in a
merge between nodes 5 and 4 as Mercurial would, 0. And thus both give
the result 'bcdE'. So we've learned precisely nothing about recursive
merge and how it compares to Mercurial from this example. The claim that
Mercurial chooses the "deepest" ancestor: also wrong and nonsensical.
The deepest ancestor is the root.

This seems to be yet another instance of "Git is incomprehensible,
therefore Git is magic, therefore Git magically works better" logic at
work.

Let's _actually_ work his original example diagram which has the
criss-crossing merges (which I guess he copied from someone who knew
what they were talking about). I'm going to ignore the blogger's
nonsensical use of arrows that point the wrong way for branch merges and
thus add cycles into the "directed acyclic graph". Here history flows
from left to right, thus the edges are right to left:

a---b-d-f---?
 \   \ /   / 
  \   X   /
   \ / \ /
    c-e-g

Let's make up a simple set of changes to go with that picture. Again,
think of each character as a line:

a = "a"
b = "a1"
c = "1a"
d = "a2"
e = "2a"
f = merge of d and c = "1a2" 
g = merge of e and b = "2a1"

When we merge f and g, our greatest common ancestor is either b or c. So
we've got the following cases:

b: we had a1 originally, and are looking at 1a2 and 2a1. So we have a
conflict at the start, but can simply choose 2 for the end as only one
side touched the end.

c: we had 1a originally, and are looking at 1a2 and 2a1. So we have a
conflict at the end, but can simply choose 2 for the start as only one
side touched the start.

Mercurial will choose whichever one of these it finds first, so we have
one conflict to resolve. It definitely does not choose 'a' as the
ancestor, which would give two conflicts.

Now what a recursive merge would do would be merging b and c first,
giving us "1a1". So now when we merge, we don't have conflicts at the
front or the back.

So yay, in this simplest of examples, it's a win. But cases where this
actually matters aren't terribly common (let's call it 1% to be
generous) and cases where it actually automatically solves the problem
for you seamlessly are actually less than half of THOSE cases.

Instead, if you've got conflicts in your recursive merge, now you've
made the whole situation more confusing. Take your blog post as Exhibit
A that most people don't understand recursive merge at all which means
when a merge goes wrong, not only do you need an expert to diagnose it,
you need an expert to tell you who the 'experts' even are.

We talk about recursive merge occasionally. But as it happens, for the
cases where ancestor ambiguity is the most interesting (merging with
backouts, exec bit changes), recursive merges don't help at all. So I
don't think they warrant the extra complexity.

The original author of Mercurial wrote about why he didn't use recursive merge strategy (link): Basically the answer is:

For the cases where ancestor ambiguity is the most interesting [...] recursive merges don't help at all. So I don't think they warrant the extra complexity

But the full answer is really interesting to read so I encourage you to do so. I'll just copy it here in case it disappear:

> Does Mercurial supports recursive merge strategy like git? It is used
> in situation when
> merge has two "common" ancestors (also know as criss-cross merge)
> 
> According to http://codicesoftware.blogspot.com/2011/09/merge-recursive-strategy.html
> Mercurial
> does not support it but I wanted to ask to make sure that nothing has changed.

Indeed. But you shouldn't judge the situation from this blog post as
it's not coherent.

In particular, the example given under "Why merge recursive is better –
a step by step example" doesn't appear to be a recursive merge situation
at all! Notice the key difference in topology as compared with the
initial diagrams: no criss-crossing merges leading up to the merge. Some
kind of bait and switch happening here.

In the example itself, Git will choose the same (single) ancestor in a
merge between nodes 5 and 4 as Mercurial would, 0. And thus both give
the result 'bcdE'. So we've learned precisely nothing about recursive
merge and how it compares to Mercurial from this example. The claim that
Mercurial chooses the "deepest" ancestor: also wrong and nonsensical.
The deepest ancestor is the root.

This seems to be yet another instance of "Git is incomprehensible,
therefore Git is magic, therefore Git magically works better" logic at
work.

Let's _actually_ work his original example diagram which has the
criss-crossing merges (which I guess he copied from someone who knew
what they were talking about). I'm going to ignore the blogger's
nonsensical use of arrows that point the wrong way for branch merges and
thus add cycles into the "directed acyclic graph". Here history flows
from left to right, thus the edges are right to left:

a---b-d-f---?
 \   \ /   / 
  \   X   /
   \ / \ /
    c-e-g

Let's make up a simple set of changes to go with that picture. Again,
think of each character as a line:

a = "a"
b = "a1"
c = "1a"
d = "a2"
e = "2a"
f = merge of d and c = "1a2" 
g = merge of e and b = "2a1"

When we merge f and g, our greatest common ancestor is either b or c. So
we've got the following cases:

b: we had a1 originally, and are looking at 1a2 and 2a1. So we have a
conflict at the start, but can simply choose 2 for the end as only one
side touched the end.

c: we had 1a originally, and are looking at 1a2 and 2a1. So we have a
conflict at the end, but can simply choose 2 for the start as only one
side touched the start.

Mercurial will choose whichever one of these it finds first, so we have
one conflict to resolve. It definitely does not choose 'a' as the
ancestor, which would give two conflicts.

Now what a recursive merge would do would be merging b and c first,
giving us "1a1". So now when we merge, we don't have conflicts at the
front or the back.

So yay, in this simplest of examples, it's a win. But cases where this
actually matters aren't terribly common (let's call it 1% to be
generous) and cases where it actually automatically solves the problem
for you seamlessly are actually less than half of THOSE cases.

Instead, if you've got conflicts in your recursive merge, now you've
made the whole situation more confusing. Take your blog post as Exhibit
A that most people don't understand recursive merge at all which means
when a merge goes wrong, not only do you need an expert to diagnose it,
you need an expert to tell you who the 'experts' even are.

We talk about recursive merge occasionally. But as it happens, for the
cases where ancestor ambiguity is the most interesting (merging with
backouts, exec bit changes), recursive merges don't help at all. So I
don't think they warrant the extra complexity.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文