【发布时间】:2011-02-06 11:56:25
【问题描述】:
我在Joel on Software阅读:
使用分布式版本控制, 分布式部分实际上不是 最有趣的部分。
有趣的是,这些 系统根据变化来思考,而不是 就版本而言。
当我们必须合并时,Subversion 试图查看两个修订版——我的 修改过的代码,和你修改过的 代码——它试图猜测如何 将它们粉碎成一个大邪恶 混乱。它通常会失败,产生 “合并冲突”的页面和页面 这不是真正的冲突,只是 Subversion 失败的地方 弄清楚我们做了什么。
相比之下,在我们工作的时候 分别在 Mercurial 中,Mercurial 是 忙着维护一系列变更集。 所以,当我们想要合并我们的代码时 在一起,Mercurial 实际上有一个 更多信息:它知道 我们每个人都改变了什么并且可以 重新应用这些更改,而不是 只看最终产品 试图猜测如何表达 在一起。
通过查看 SVN 的存储库文件夹,我的印象是 Subversion 将每个修订都维护为 changeset。据我所知,Hg 同时使用 changeset 和 snapshot 而 Git 纯粹使用 snapshot 来存储数据。
如果我的假设是正确的,那么一定有其他方法可以使 DVCS 中的合并变得容易。那些是什么?
* 更新:
- 我对技术角度更感兴趣,但非技术角度的答案是可以接受的
- 更正:
- Git 的概念 模型完全基于快照。快照可以存储为其他快照的差异,只是差异纯粹是为了存储优化。 – Rafał Dowgird的comment
- 从非技术角度:
- 这只是文化问题:如果合并很困难,DVCS 将根本无法工作,因此 DVCS 开发人员投入了大量时间和精力来简化合并。 CVCS 用户 OTOH 习惯于糟糕的合并,因此开发人员没有动力让它工作。 (当您的用户为一些垃圾支付给您同样高的费用时,为什么要制作一些好的东西?)
...
回顾一下:DVCS 的全部意义在于拥有许多分散的存储库并不断地来回合并更改。如果没有良好的合并,DVCS 根本就没用。然而,CVCS 仍然可以在糟糕的合并中存活下来,特别是如果供应商可以调整其用户以避免分支。 – Jörg W Mittag 的 answer
- 这只是文化问题:如果合并很困难,DVCS 将根本无法工作,因此 DVCS 开发人员投入了大量时间和精力来简化合并。 CVCS 用户 OTOH 习惯于糟糕的合并,因此开发人员没有动力让它工作。 (当您的用户为一些垃圾支付给您同样高的费用时,为什么要制作一些好的东西?)
- 从技术角度:
- 记录历史的真实 DAG 确实有帮助!我认为主要区别在于 CVCS 并不总是将合并记录为具有多个父级的变更集,从而丢失了一些信息。 – tonfa 的 comment
- 因为合并跟踪,以及每个修订版本都知道其父版本这一更基本的事实。 ...当每个修订版(每个提交),包括合并提交,都知道它的父级(对于合并提交,这意味着拥有/记住多个父级,即合并跟踪),您可以重建修订图(DAG = Direct Acyclic Graph)历史。如果您知道修订图,则可以找到要合并的提交的共同祖先。而且,当您的 DVCS 知道自己如何找到共同祖先时,您不需要将其作为参数提供,例如在 CVS 中。
.
请注意,两个(或多个)提交的共同祖先可能不止一个。 Git 使用所谓的“递归”合并策略,它合并合并基础(共同祖先),直到您留下一个虚拟/有效的共同祖先(在某些简化中),并且可以进行简单的 3 路合并。 – Jakub Narębski's answer
【问题讨论】:
-
“Git 纯粹使用快照来存储数据”——这只是部分正确。 Git 的conceptual 模型完全基于快照。快照可以存储为其他快照的差异,只是差异纯粹是为了存储优化。
-
请注意,HgInit 是错误的,或者至少在该页面的某个方面具有误导性:它声称如果您移动一个函数并同时更改它,DVCSes 将能够合并它。实际上,这种移动/复制跟踪只发生在整个文件级别。
-
@LaurensHolst:我的理解是 Git 确实会跟踪这种变化(尽管我还没有运行测试来确认)。我不知道 Mercurial 有没有。
-
有人愿意将它与stackoverflow.com/q/2475831/157957 和/或stackoverflow.com/q/43995/157957 合并吗?我认为所有这些都有有趣的答案(以及一些相当过时的答案),但它们涵盖的领域完全相同。
标签: svn git version-control mercurial dvcs