93

在 Subversion 或 CVS 中处理对分支的多次合并只是必须经历的事情之一。在 Mercurial(以及可能任何其他分布式系统)中跟踪分支和合并非常容易,但我不知道为什么。还有人知道吗?

我的问题源于这样一个事实,即使用 Mercurial,您可以采用类似于 Subversions/CVS 中央存储库的工作实践,并且一切都会正常工作。您可以在同一个分支上进行多次合并,并且您不需要无休止的带有提交编号和标签名称的纸片。

我知道最新版本的 Subversion 能够跟踪分支的合并,所以你不会遇到同样程度的麻烦,但这是他们方面的一个巨大而重大的开发,它仍然不能完成开发团队会做的所有事情喜欢这样做。

这一切的运作方式必须有根本的不同。

4

6 回答 6

115

在 Subversion(和 CVS)中,存储库是最重要的。在 git 和 mercurial 中,实际上并没有以同样的方式存储库的概念。这里的变化是中心主题。

+1

CVS/SVN 的麻烦在于这些系统 记得更改的父级。在 Git 和 Mercurial 中,一个提交不仅可以有多个子级,还可以有多个父级!

使用其中一种图形工具gitkhg view. 在以下示例中,分支 #2 在提交 A 处从 #1 分叉,并且已合并一次(在 M 处,与提交 B 合并):

o---A---o---B---o---C         (branch #1)
     \       \
      o---o---M---X---?       (branch #2)

注意 A 和 B 如何有两个孩子,而 M 有两个父母。这些关系记录在存储库中。假设分支 #2 的维护者现在想要合并分支 #1 的最新更改,他们可以发出如下命令:

$ git merge branch-1

并且该工具将自动知道基础是 B——因为它记录在提交 M 中,它是 #2 提示的祖先——并且它必须合并 B 和 C 之间发生的任何事情。CVS 不记录此信息, SVN 1.5 之前的版本也没有。在这些系统中,图表如下所示:

o---A---o---B---o---C         (branch #1)
     \    
      o---o---M---X---?       (branch #2)

其中 M 只是 A 和 B 之间发生的所有事情的巨大“压扁”提交,应用于 M 之上。请注意,在契约完成后,没有留下任何痕迹(除了可能在人类可读的注释中)M 的位置确实起源于,也不是有多少次提交一起崩溃——使历史更加难以理解。

更糟糕的是,执行第二次合并变成了一场噩梦:必须弄清楚第一次合并时的合并基础是什么(并且必须首先知道 有合并!),然后呈现向工具提供信息,以便它不会尝试在 M 之上重放 A..B。当密切协作时,所有这些都非常困难,但在分布式环境中根本不可能。

一个(相关的)问题是没有办法回答这个问题:“X 是否包含 B?” 其中 B 是一个潜在的重要错误修复。那么,为什么不在提交中记录该信息,因为它在合并时是已知的!

P.-S。-- 我没有使用 SVN 1.5+ 合并录制功能的经验,但是工作流程似乎比分布式系统中的人为得多。如果确实如此,那可能是因为——正如上面评论中提到的——重点放在了存储库组织上,而不是更改本身。

于 2008-09-04T20:32:43.123 回答
12

因为 Subversion(至少 1.4 及以下版本)不跟踪已合并的内容。对于 Subversion,合并基本上与任何提交相同,而在其他版本控制(如 Git)上,已合并的内容会被记住。

于 2008-09-04T16:02:52.197 回答
7

Hg 没有受到任何已经提供的答案的影响,它提供了卓越的合并功能,因为它在合并更改时使用了更多信息(hginit.com):

例如,如果我稍微改变一个函数,然后将它移动到其他地方,Subversion 并不会真正记住这些步骤,所以当需要合并时,它可能会认为一个新函数突然出现. 而 Mercurial 会分别记住这些内容:函数更改,函数移动,这意味着如果您也稍微更改了该函数,Mercurial 更有可能成功合并我们的更改。

当然,记住上次合并的内容(此处提供的大多数答案都解决了这一点)也是一个巨大的胜利。

然而,这两个改进都是有问题的,因为 subversion 1.5+ 以 subversion 属性的形式存储了额外的合并信息:这些信息可用,没有明显的理由说明 subversion 合并不能像 Hg 或 Git 那样成功地实现合并。不过,我不知道它是否确实如此,但听起来颠覆开发人员正在解决这个问题。

于 2010-07-05T13:27:13.093 回答
4

我想这可能部分是因为 Subversion 有一个中央服务器的想法以及一个绝对的修订时间线。Mercurial 是真正分布式的,没有这样的绝对时间线参考。这确实允许 Mercurial 项目形成更复杂的分支层次结构,以便按子项目添加功能和测试周期,但是团队现在需要更加积极地保持合并以保持最新状态,因为他们不能只点击更新并完成它.

于 2008-09-04T15:55:29.437 回答
3

在 Subversion(和 CVS)中,存储库是最重要的。在 git 和 mercurial 中,实际上并没有以同样的方式存储库的概念。这里的变化是中心主题。

我也没有过多考虑您将如何实现,但我的印象(基于痛苦的经验和大量阅读)是这种差异使得在非基于存储库的系统中合并和分支变得如此容易。

于 2008-09-04T15:56:42.010 回答
1

我只有 Subversion 的经验,但我可以告诉你 TortoiseSVN 中的合并屏幕非常复杂。幸运的是,它们包括一个试运行按钮,这样您就可以查看自己是否做得对。复杂之处在于您要合并到哪里的配置。一旦你为合并进行了设置,合并通常会很好。然后,您需要解决所有冲突,然后将合并的工作副本提交到存储库。

如果 Mercurial 可以使合并的配置更容易,那么我可以说这将使合并比 Subversion 更容易 100%。

于 2008-09-04T15:40:21.783 回答