git 为什么在 Mercurial 中分支和合并比在 Subversion 中更容易?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43995/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 16:03:15  来源:igfitidea点击:

Why is branching and merging easier in Mercurial than in Subversion?

svngitversion-controlmercurial

提问by Nick Pierpoint

Handling multiple merges onto branches in Subversion or CVS is just one of those things that has to be experienced. It is inordinately easier to keep track of branches and merges in Mercurial (and probably any other distributed system) but I don't know why. Does anyone else know?

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

My question stems from the fact that with Mercurial you can adopt a working practice similar to that of Subversions/CVSs central repository and everything will work just fine. You can do multiple merges on the same branch and you won't need endless scraps of paper with commit numbers and tag names.

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

I know the latest version of Subversion has the ability to track merges to branches so you don't get quite the same degree of hassle but it was a huge and major development on their side and it still doesn't do everything the development team would like it to do.

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

There must be a fundamental difference in the way it all works.

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

回答by Damien Diederen

In Subversion (and CVS), the repository is first and foremost. In git and mercurial there is not really the concept of a repository in the same way; here changes are the central theme.

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

+1

+1

The hassle in CVS/SVN comes from the fact that these systems do notremember the parenthood of changes. In Git and Mercurial, not only can a commit have multiple children, it can also have multiple parents!

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

That can easily observed using one of the graphical tools, gitkor hg view. In the following example, branch #2 was forked from #1 at commit A, and has since been merged once (at M, merged with commit B):

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

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

Note how A and B have two children, whereas M has two parents. These relationships are recordedin the repository. Let's say the maintainer of branch #2 now wants to merge the latest changes from branch #1, they can issue a command such as:

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

$ git merge branch-1

and the tool will automatically know that the baseis B--because it was recorded in commit M, an ancestor of the tip of #2--and that it has to merge whatever happened between B and C. CVS does not record this information, nor did SVN prior to version 1.5. In these systems, the graph would look like:

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

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

where M is just a gigantic "squashed" commit of everything that happened between A and B, applied on top of M. Note that after the deed is done, there is no trace left(except potentially in human-readable comments) of where M did originate from, nor of how manycommits were collapsed together--making history much more impenetrable.

其中 M 只是 A 和 B 之间发生的所有事情的巨大“压扁”提交,应用于 M 之上。请注意,在行为完成后,没有留下任何痕迹(除了可能在人类可读的评论中)M 所在的位置确实起源于,也不知道有多少提交被折叠在一起——让历史变得更加难以理解。

Worse still, performing a second merge becomes a nightmare: one has to figure out what the merge base was at the time of the first merge (and one hasto knowthat there has been a merge in the first place!), then present that information to the tool so that it does not try to replay A..B on top of M. All of this is difficult enough when working in close collaboration, but is simply impossible in a distributed environment.

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

A (related) problem is that there is no way to answer the question: "does X contain B?" where B is a potentially important bug fix. So, why not just record that information in the commit, since it is knownat merge time!

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

P.-S. -- I have no experience with SVN 1.5+ merge recording abilities, but the workflow seems to be much more contrived than in the distributed systems. If that is indeed the case, it's probably because--as mentioned in the above comment--the focus is put on repository organization rather than on the changes themselves.

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

回答by htanata

Because Subversion (at least version 1.4 and below) doesn't keep track of what have been merged. For Subversion, merging is basically the same as any commit while on other version control like Git, what have been merged are remembered.

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

回答by Tomislav Nakic-Alfirevic

Untouched by any of the already provided answers, Hg offered superior merge capabilities because it uses more information when merging changes (hginit.com):

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

For example, if I change a function a little bit, and then move it somewhere else, Subversion doesn't really remember those steps, so when it comes time to merge, it might think that a new function just showed up out of the blue. Whereas Mercurial will remember those things separately: function changed, function moved, which means that if you also changed that function a little bit, it is much more likely that Mercurial will successfully merge our changes.

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

Of course, remembering what was last merged (the point addressed by most of the answers provided here) is also a huge win.

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

Both improvements, however, are questionable since subversion 1.5+ stores additional merge information in the form of subversion properties: that information available, there's no obvious reason why subversion merge couldn't implement merge as successfully as Hg or Git. I don't know if it does, though, but it certainly sounds like subversion developers are on their way to get around this issue.

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

回答by Evil Andy

I suppose this might partially be because Subversion has the idea of a central server along with an absolute time line of revisions. Mercurial is truly distributed and has no such reference to an absolute time line. This does allow Mercurial projects to form more complicated hierarchies of branches for adding features and testing cycles by sub project however teams now need to much more actively keep on top of merges to stay current as they can't just hit update and be done with it.

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

回答by Stephen Darlington

In Subversion (and CVS), the repository is first and foremost. In git and mercurial there is not really the concept of a repository in the same way; here changesare the central theme.

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

I've not thought much about how you'd implement either but my impression (based on bitter experience and lots of reading) is that this difference is what makes merging and branching so much easier in non-repository based systems.

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

回答by RedWolves

I only have experience with Subversion but I can tell you that the merge screen in TortoiseSVN is horribly complicated. Luckily they include a dry run button so that you can see if you are doing it right. The complication is in the configuration of what you want to merge to where. Once you get that set up for the merge the merge generally goes fine. Then you need to resolve any and all conflicts and then commit your merged in working copy to the repository.

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

If Mercurial can make the configuration of the merge easier then I can say that would make merging 100% easier then Subversion.

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