与git或mercurial相比,svn中的合并有区别吗?


12

根据我的理解,SVN是“易于分支。合并困难”。这是为什么?它们如何合并有区别吗?

git  svn  mercurial  dvcs 

Answers:


21

请参阅我的Stack Overflow答案,了解非常具体的情况,其中Mercurial(和Git)合并没有问题,并且Subversion给您带来虚假的冲突。这种情况是在重命名某些文件的分支上完成的简单重构。

关于tdammers的回答,那么那里存在许多误解:

  • Subversion,Mercurial和Git都跟踪项目的整个存储库范围的快照。将它们称为版本修订版变更集没有区别。它们在逻辑上都是一组文件的原子快照。

  • 合并时,提交的大小没有区别。所有这三个系统均使用标准三向合并算法合并,该算法的输入为

    • 最伟大的共同祖先版本
    • 一个分支上的版本
    • 其他分支上的版本

    不要紧,怎么两个分支版本中创建。自祖先版本以来,您可以使用1000次小的提交,也可以使用1次提交。重要的是文件的最终版本。(是的,这很令人惊讶!是的,很多DVCS指南都犯了这个可怕的错误。)

他还提出了一些关于差异的要点:

  • Subversion有一些“伏都教”,您可以在其中合并/trunk/branches/foo。Mercurial和Git不使用此模型-分支直接在历史记录中建模。因此,历史记录变成有向无环图,而不是线性的。这个模型比Subversion使用的模型简单得多,并且省去了许多极端情况。

  • 您可以轻松地延迟合并,甚至可以其他人来处理。如果hg merge给您带来大量冲突,那么您可以要求您的同事hg pull与您联系,然后他就拥有完全相同的状态。因此他可以hg merge而且也许他比您更能解决冲突。

    这是在那里你需要更新的Subversion非常困难面前你可以提交。您不能只忽略服务器上的更改并继续在自己的匿名分支上进行提交。在一般情况下,颠覆的力量你玩弄一个肮脏的工作拷贝你的时候svn update。这是有风险的,因为您没有将更改存储在安全的地方。Git和Mercurial让您先提交,然后根据需要进行更新和合并。

Git和Mercurial比Subversion更好地合并的真正原因是实现方面的问题。即使很清楚正确的答案是什么,Subversion也无法解决重命名冲突。Mercurial和Git可以轻松处理这些问题。但是,没有理由说Subversion也不能处理这些问题-集中化当然不是原因。


4
好答案!如果可以的话,我将投票两次。:)我还补充一点,SVN书,你指的是SO答案明明白白承认“Subversion的合并跟踪功能有着极其复杂的内部实现......” -这本身是一个非常好的迹象是功能是不可靠的
蚊蚋

2
...即使采用这种极其复杂的实现方式,在简单的情况下也无法正确找出共同祖先。
Jan Hudec 2012年

关于延迟合并-不了解-使用SVN,我的同事可以更新到/签出中继,然后从我的分支合并到其中。
Gill Bates

@GillBates:我说的是一种情况,即您trunk在SVN中工作时尚未开始工作分支。使用DVCS,您可以提交而无需共享,但是在SVN中,您svn commit将直接影响在同一分支上工作的其他人。即使我们两个人在SVN中的一个分支上工作,我也无法提交我的工作而不必立即与您的工作合并。这使提交有些令人恐惧-这对于版本控制系统来说是令人恐惧的特性!:-)
马丁·盖斯勒

6

核心问题在于这些系统表示版本化目录结构的方式。

Subversion整个系统围绕的基本概念是版本(或在svn术语中为“修订”)的概念:文件在特定点的快照。只要历史记录是完全线性的,就可以了,但是如果您需要合并两条独立开发线中的更改,svn必须比较两者的当前版本,然后在最后一个共享版本之间进行三向比较和两个头部版本。看起来很容易改变的线条可以很容易地解决,其中一个不会改变。在两个头上完全相同地偏离的线条较难,但通常是可行的;svn会说,以不同的方式偏离的行是“人类,我无法弄清楚,请帮我解决这个问题。”

相比之下,git和mercurial跟踪变更集而不是版本。整个存储库是一棵变更集树,每个变更集都取决于一个父集,其中一个父变更集可以具有任意数量的子代,并且树根表示一个空目录。换句话说,git / hg说“首先我什么都没有,然后应用了此补丁,然后再应用该补丁,等等”。当您需要合并两条开发线时,git / hg不仅知道当前每个头的外观以及上一个通用版本的外观,而且还知道过渡是如何发生的,从而可以进行更智能的合并。

使DVCS中的合并更容易的另一件事是将提交推送的概念分开的间接结果,并且允许随时在同一存储库的任何两个克隆之间进行各种交叉合并。使用svn时,人们倾向于提交大型变更集,而这些变更集通常具有不相关的变更,因为提交也是中央存储库上的更新,会影响所有其他团队成员;如果您提交的版本不完整,每个人都会生您的气。由于大多数设置都涉及联网的svn服务器,因此提交还涉及通过网络泵送数据,这意味着提交会给工作流程带来相当大的延迟(尤其是当您的工作副本已过时且必须先拉时)。使用git和mercurial时,提交在本地进行,并且由于两者都非常有效地处理本地文件系统,因此通常会立即完成。结果,人们(一旦习惯了)就进行了微小的增量更改,然后在其生效时,一口气推十几次提交。然后,当合并时间到来时,SCM将获得更多详细信息,并可以更好地安全自动地解决冲突。

还有一些很棒的细节使事情变得更加容易:

  • 您可以有多个脑袋,但仍然可以选择其中一个。与Subversion不同,您无需在再次提交之前合并pull,update和merge-多头保持不变,直到您选择合并
  • 目录没有得到特别处理;相反,该路径仅被视为一个大文件名,并且所有目录都必须始终处于同一修订版本。这意味着您不能在项目的子文件夹处于不同修订版本的情况下进行Subversion伏都教,但这也意味着工作副本不太可能成为巨大的难以管理的混乱局面,更有趣的是,移动并不表示为删除-and-add(如果不是用于改型元数据,它将在svn中完全中断),而只是作为重命名;如果您移动文件,则将保留其整个历史记录;合并甚至可以将在移动在另一个分支中对同一文件的非移动版本进行的更改应用于移动的文件
  • 在大多数情况下,您实际上甚至不需要分支:相反,您只需克隆整个存储库即可。克隆很便宜,特别是如果它是在同一文件系统上完成的,并且如果您决定要摆脱克隆,则只需删除它所在的目录即可。您甚至不需要为此使用hg或git。
  • 可以合并的内容几乎没有限制。您可以具有同一存储库的六个克隆,然后从A到B,然后从C到B,然后从B到D,再从C到D,然后从B合并(或者,推或拉;通常不需要显式合并)从A,D到E,随时随地进行。
  • 您可以通过以下方式测试合并:克隆要合并的存储库之一,然后从另一个存储库中拉入。如果它满足您的要求,则可以将其推回实际目标;如果不满足要求,则可以丢弃该克隆并重新开始。

2
我必须提及一些更正并添加答案:1. SVN修订版是每个存储库的全局文件,修订版表示某个时候回购中的所有文件。2.合并技术在SVN和DVCS 中基本上是通用的-如果合并文件中的文件仅更改了同样,合并将为SVN和DVCS产生相同数量的冲突-所有SCM仍在字符串级而不是逻辑块上运行3。SVN中的大型提交不是体系结构弱的结果,而是因为用户通常是懒惰的白痴-他们忽略了基本模式。如果/ dev / brain和/ dev / hands有效,则Branch | merge可以在SVN中工作
Lazy Badger 2012年

2
第2部分:DVCS中的智能合并主要是因为与Subversion相反,它们跟踪并处理文件的重命名,而SVN根本不执行,因此-任何操作,即处理文件,在一侧更改并重命名。第二,会失败。用分支和克隆进行分支只是具有相同生存权的不同分支策略,使用“ ...取决于...”
Lazy Badger 2012年

@ LazyBadger:互惠生。Subversion 确实会跟踪移动/重命名,这会导致虚假冲突,部分原因是它在合并中对重命名的处理很容易出错,部分原因是有些情况很难或不可能正确处理。后面就是为什么git(并通过复制将其复制)为什么跟踪重命名并在合并时猜测它们的原因。如果内容仍然足够相似(可以在需要时进行合并),并且不会做其他愚蠢的事情,那么这很好用。
Jan Hudec 2012年

@JanHudec-抱歉,SVN句柄不会以原子一动作(DVCS方式-“重命名”)移动|重命名,而是作为“ delete + ...”,因此会产生树冲突,而在DVCS中不会发生(真正的重命名))。Mercurial 轨道显式hg mvhg addremove --similarity...重命名,而Git使用启发式,但两个都处理重命名。即使在合并的文件中有1个字符串差异,我也可能会遇到树冲突!抱歉,您必须重新学习Subversion的某些方面。
Lazy Badger 2012年

5
现在我们已经掌握了相当技术性:-) Subversion和Mercurial轨道副本,而不是重命名。两个系统都跟踪rename a bas,copy a b; remove a并且都在一个原子提交中完成。合并行为的差异源于对极端案例的不同处理,以及Subversion比Mercurial和Git允许更多的合并。最后,Git 在合并和登录时检测到重命名-我们也正在考虑将其添加到Mercurial中。
马丁·盖斯勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.