git - Mercurial merge 策略 vs Git merge 策略

标签 git merge mercurial

我使用 git 多年,最近为了一个项目改用 mercurial。在过去的 6 个月里,我已经学会了如何通过命令行很好地使用 Mercurial。

这可能是我的想象,但在我看来,mercurial 在 merge 方面要差得多,并且会导致更多的文件冲突。我会经常将默认分支 merge 到我的功能分支中,它有时会做一些非常时髦的事情,并且无法自动 merge 看起来应该在视觉上很好地 merge 的文件 - I.E.同一行没有变化等。

我已经做了相当多的研究来了解 merge 算法可能有什么不同,但运气很差。大多数文章都是人们关于 git 和 mercurial 如何在幕后工作的意见和信息,并没有过多地关注 merge 算法本身以及优势/劣势以及差异的通俗易懂的示例。

我总是使用良好的 merge 策略并通过树向上 merge ,并且在没有首先 merge 到远程分支以确保没有冲突的情况下从不向下 merge 到 default(hg)/master(git) 分支。

到目前为止,我在研究中发现的是:

1) Mercurial 无法 merge 或在与多个父级 merge 时出现问题。我不确定有人会遇到这种情况,但也许这很常见?

这是真的吗?这会不会在日常开发中更频繁地导致 merge 冲突?

2) Mercurial 不支持 octopus merge ,而 git 支持。

对于 Octopus merge ,我说“谁在乎!”,这不是必需的。

除此之外, merge 算法似乎是平等创建的?是否可以更改 merge 算法?有没有这方面的好文章?

如果您发布有关 k3diff、p4merge 和 meld 等 merge 工具的信息,那么您就错过了 Gist - 我想要有关解决冲突之前的自动 merge 策略的信息。

感谢您提供任何有用的引用和/或信息!

最佳答案

1) Mercurial cannot merge or has issues merging with multiple parents. I'm not sure how someone ends up in this situation, but maybe it is common?

Is this true? Would this cause merge conflicts more often in every-day development?

不,这不是真的——至少如所声称的那样,这似乎有点毫无意义。

进行基于提交图的 merge 的根本问题与查找 Lowest Common Ancestor or LCA 有关。 .在中,总是有一个 LCA,因此它是三向 merge 的明显输入:它是通常基础提交中的基础,左侧/本地/--我们的提交,右侧/远程/--他们的操作。

然而,在提交的 DAG 中,可能有多个 LCA 节点。 Mercurial 对此的默认解决方案是任意选择或多或少。 Git 的默认解决方案是使用-s 递归 策略选择所有 并 merge 它们。这种“内部” merge 导致单个最终提交,然后 Git 将其用作 merge 基础。您可以重写它以使用 -s resolve 执行与 Mercurial 相同的操作:任意选择或多或少的一个,并将其用作基础。

Mercurial 有几个实验性的替代 merge 策略(参见,例如 BidMerge),但没有一个是“开箱即用的”,不像 Git 的四个 -s 策略。

多个 merge 基础主要发生在某人进行“交叉 merge ”时。参见 How do criss-cross merges arise in Git?在某些工作流程中,这种情况永远不会发生,而且在实践中也并不常见。

2) Mercurial doesn't support octopus merging, where git does.

For octopus merging, I say "who cares!", this isn't a necessity.

没错。任何 Octopus merge 都可以通过一系列成对 merge 来模拟。不过,它们特别适合炫耀。 :-)

Other than that, it seems that the merge algorithms are created equally?

不,因为 Mercurial 和 Git 使用不同的算法来跟踪文件名。这里的问题是:一旦你有了三向 merge 的三个输入,谁说 base 中的文件 path/to/f 就是 与左侧的 path2/f2 和/或右侧的 path3/f3 相同 文件?我们应该将哪些文件配对,或者像我喜欢的那样识别

Mercurial 对此的回答是通过 list 和记录的目录操作(记录的重命名或复制)来跟踪文件身份,而 Git 的是通过内容匹配动态确定文件身份。然而,完全动态确定在计算上过于昂贵,因此 Git 作弊:如果两个文件在 base-vs-left 或 base-vs-right 中具有相同路径,则这两个文件被识别为“相同” “文件。这只留下没有配对的路径名来动态识别。

还必须处理在最终结果中使用哪个路径名。在这里,Mercurial 让您在 merge 命令运行时进行选择,而 Git 只是将所有 名称填充到其索引中,允许稍后延迟名称选择。

不过,一旦被适本地识别和命名, merge 过程本身是相同的:找出哪一方更改了哪个文件。如果只有一方更改了文件,则使用该方的版本。否则,对三个输入进行文件级 merge (Git 在内部称其为低级 merge )。这需要计算差异或跟踪和组合单个变更集,Git 和 Mercurial 都选择直接的“差异基础与提示”方法。 (因为 Git 总是存储快照,所以它有点被迫这样。Mercurial 有时 存储快照,所以它也有点被迫。)但是它们的内部差异引擎也不相同,所以这也可以产生一些不同的结果。

Is it possible to change the merging algorithms? Are there any great articles on this?

是的:Git 有 -s 参数,而 Mercurial 在内部都是可插入的。

没有,据我所知。我正在研究 book , 除了我这几天不积极工作,有一份不同的工作,也不是专门针对这些;但理论章节(至少在某种程度上接近完成)给出了适当的背景。

关于git - Mercurial merge 策略 vs Git merge 策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49560696/

相关文章:

git - merge Git 存储库

algorithm - 自上而下的范围合并?

list - 通过时间戳合并列表中的列表

git - 本地更改已 checkin 索引但未提交。本地未提交的更改,未 checkin 索引

git - `git checkout ...` 是做什么的?

git - 理论上可以在浏览器扩展中捆绑 Mercurial 或 Git 吗?

mercurial - 当 "a branch of the same name already exists"时创建分支?

eclipse - 如何从MercurialEclipse插件存储库位置字段中删除旧的存储库URL

git - 如何使用 Jenkins 为许多 repos 创建和推送新的 Github 分支?

Git:致命:名为 'master' 的分支已经存在