在 Subversion(和 CVS)中,存储库是最重要的。在 git 和 mercurial 中,实际上并没有以同样的方式存储库的概念。这里的变化是中心主题。
+1
CVS/SVN 的麻烦在于这些系统不
记得更改的父级。在 Git 和 Mercurial 中,一个提交不仅可以有多个子级,还可以有多个父级!
使用其中一种图形工具gitk
或hg
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+ 合并录制功能的经验,但是工作流程似乎比分布式系统中的人为得多。如果确实如此,那可能是因为——正如上面评论中提到的——重点放在了存储库组织上,而不是更改本身。