为什么Git不将分支名称存储为提交的一部分?

时间:2011-10-18 13:00:48

标签: git mercurial branch git-branch

请注意:我不是要重新启动Mercurial或Git更好的论点,我只是有一个技术问题,我作为Mercurial用户,不明白。我也不确定SO是否是提出这样一个问题的正确位置,但编程相关。

关于两个版本控制系统Git和Mercurial如何从用户的角度(例如What is the Difference Between Mercurial and Git?http://felipec.wordpress.com/2011/01/16/mercurial-vs-git-its-all-in-the-branches/)彼此不同,已经有很多讨论,主要区别在于处理分支机构。我已经阅读了很多这些讨论,但我一直在问自己这个问题:

为什么Git不将分支名称存储为提交的一部分?

我真的没有理由不这样做;这意味着数据不能简单地消失,因为没有参考(标记,分支,等等)。

我认为将分支存储在提交中是Mercurial的一大优势,因为这会使丢失数据变得更加困难。

Git的主要观点是支持Git的分支模型,你可以简单地删除分支,并不会阻止Git在每次提交时存储分支的名称:如果删除分支的提交,对该分支的引用也是如此。它也不会干扰“廉价分支”的论点:分支管理起来不会更昂贵。我并不认为所需的额外存储应该引起关注:每次提交只需几个字节。

2 个答案:

答案 0 :(得分:14)

关于Git和Mercurial分支的权威来源之一是SO问题:

Git and Mercurial - Compare and Contrast

  

在Git中,引用(分支,远程跟踪分支和标记)驻留在提交的DAG之外。

(允许管理有关分支的不同命名空间,用于本地和远程分支)

你对Mercurial有类似的概念,书签分支(可以推/拉)。

请注意,在Git中,数据不会“消失”,因为没有引用:您仍然有reflog来检索那些未引用的提交。

  

为什么Git不将分支名称存储为提交的一部分?
  我真的没有理由不这样做

我们的想法是将 更改(提交)与为什么分开,即从更改的上下文(分支的名称)中分离。
由于您可以fast-forward merge分支,因此一个分支的提交可以随时成为另一个分支的一部分。

这就是为什么Jakub Narębski质疑Mercurial“命名分支”的设计(在变更集元数据中嵌入了分支名称),特别是对于全局命名空间,不太适合分布式版本控制系统。

您创建了一个分支来隔离开发工作(请参阅“When should you branch?”),但对于DVCS,应该在任何分支名称下发布该开发工作(提交集)。您定义的本地上下文(分支名称)一旦发布到另一个Git仓库,可能无效。

答案 1 :(得分:8)

Mercurial的基本操作模型非常简单,匿名分支形成有向无环图(DAG),因此这些分支名称并不重要,您将更少地处理它们。命名分支主要用于组织目的(发布分支等),我认为全局命名空间更有意义,或者至少不那么令人反感。

Git拥有比Mercurial更复杂和管理的分支模型,即使您的本地更改被视为一个单独的命名分支,并且面对如此多的命名分支,您必须引入命名空间来管理它们。出于同样的原因,Git具有快进合并的概念,这不适用于Mercurial,因为您不会首先创建单独的分支。

这两个概念都增加了额外的复杂性,同时阻止了有用的功能,比如存储分支名称和提交。这是因为你不能存储没有一些全局空间的命名空间分支,而git没有。

VonC在上面引用的命名空间参数中的缺陷是,如果你和我都创建了一个名为“x”的分支,它就会假定存在问题。没有,就像创建命名分支时没有问题,合并它,然后创建另一个具有相同名称的分支。精心挑选的名称描述了分支的作用,无论作者是谁,如果您需要区分更多,作者与分支名称一起存储,并且所有这些都是永久性的。

我认为Mercurial项目的一个非常好的决定是将分支名称与提交一起存储。就像提交消息和作者一样,工作的上下文(分支)是重要且有用的元信息。这使得在检查历史记录时更容易看到变更集的流程,因为您可以看到它们所构成的上下文。在Git中,我经历过如果没有这些信息,历史很快变成一堆麻烦的线条很难制作的头部或尾部。我认为拥有这个非常值得权衡没有命名空间。

我认为你可以说哲学上的区别在于Mercurial将命名分支视为永久元数据,提供了一系列提交的额外信息,而Git分支是一个非版本管理系统,供开发人员使用。 DAG。顺便提一下,Mercurial还以“书签”的名称(从版本1.8开始是核心功能),但它们实际上更像是一种跟踪工具,并且被视为标签而不是分支。