关于版本控制:Mercurial和Git有什么区别?

What is the Difference Between Mercurial and Git?

我已经在Windows上使用Git一段时间了(使用MSysGit),我喜欢分布式源代码管理的思想。最近我一直在研究汞,它看起来很有趣。但是,我不能把我的头绕在Hg和Git之间的区别上。

有没有人对Git和Hg做过并列比较?我有兴趣知道hg和git有什么不同,而不必跳到fanboy的讨论中去。


这些文章可能有助于:

  • Git和Mercurial:请放松(Git是Macgyver,Mercurial是James Bond)
  • Mercurial和Git的区别

编辑:将Git和Mercurial与名人进行比较似乎是一种趋势。还有一个:

  • Git是韦斯利·斯奈普斯,Mercurial是丹泽尔·华盛顿


我研究的是mercurial,但从根本上讲,我相信这两个系统是等效的。它们都使用相同的抽象:组成历史的一系列快照(变更集)。每个变更集都知道它来自哪里(父变更集),并且可以有许多子变更集。最近的hg git扩展在mercurial和git之间提供了一个双向的桥梁,这表明了这一点。

Git非常关注改变这个历史图表(包括所有后果),而Mercurial不鼓励改写历史,但无论如何都很容易做到,这样做的后果正是您应该期待的(也就是说,如果我修改了您已经有的变更集,您的客户会认为它是新的,如果您我的电话)。所以Mercurial倾向于使用非破坏性命令。

至于轻量级分支,那么Mercurial一直以来都支持具有多个分支的存储库,我一直认为。具有多个分支的Git存储库正是这样:单个存储库中存在多个分散的开发链。然后Git向这些链添加名称,并允许您远程查询这些名称。Mercurial的书签扩展名添加了本地名称,使用Mercurial 1.6,您可以在推/拉时移动这些书签。

我使用Linux,但显然TortoiseHg比Windows上的Git等效软件更快、更好(这是因为Windows文件系统的性能较差)。http://github.com和http://bitback.org都提供在线托管,bitback的服务很好,响应速度也很快(我还没有尝试过github)。

我选择了Mercurial,因为它让我感觉干净优雅——我被我用Git得到的shell/perl/ruby脚本所耽误。如果你想知道我的意思,可以试着浏览一下git-instaweb.sh文件:它是一个shell脚本,生成一个ruby脚本,我认为它运行一个Web服务器。shell脚本生成另一个shell脚本来启动第一个ruby脚本。还有一点Perl,作为很好的度量。

我喜欢将Mercurial和Git与James Bond和Macgyver进行比较的博客文章——Mercurial在某种程度上比Git更低调。在我看来,使用Mercurial的人并不容易被打动。这反映在每个系统是如何完成Linus所描述的"有史以来最酷的合并"的。。在Git中,可以通过执行以下操作与不相关的存储库合并:

1
2
3
4
5
6
git fetch <project-to-union-merge>
GIT_INDEX_FILE=.git/tmp-index git-read-tree FETCH_HEAD
GIT_INDEX_FILE=.git/tmp-index git-checkout-cache -a -u
git-update-cache --add -- (GIT_INDEX_FILE=.git/tmp-index git-ls-files)
cp .git/FETCH_HEAD .git/MERGE_HEAD
git commit

这些命令在我看来相当神秘。在Mercurial中,我们做到了:

1
2
3
hg pull --force <project-to-union-merge>
hg merge
hg commit

请注意,mercurial命令是多么简单,一点也不特殊——唯一不寻常的是--force标志指向hg pull,这是必需的,因为当您从一个不相关的存储库中提取时,mercurial将以其他方式中止。正是这种差异让我觉得反复无常更优雅。


Git是一个平台,Mercurial只是一个应用程序。Git是一个版本化的文件系统平台,它恰巧与DVCS应用程序一起提供,但与平台应用程序一样,它更复杂,而且比聚焦应用程序的边缘更粗糙。但这也意味着Git的VCS非常灵活,并且有大量的非源代码控制功能,您可以使用Git进行操作。

这就是差异的本质所在。

Git最好从一开始就被理解——从存储库格式开始。斯科特·查孔的《Git Talk》是一本很好的入门书。如果你试图在不知道引擎盖下发生了什么的情况下使用Git,你会在某个时刻感到困惑(除非你坚持只使用非常基本的功能)。当你只需要一个用于日常编程程序的DVC时,这听起来可能很愚蠢,但是Git的天才在于存储库格式实际上非常简单,而且你可以很容易地理解Git的整个操作。

对于一些更注重技术的比较,我个人看到的最好的文章是DustinSallings':

  • Mercurial和Git的区别
  • Reddit线程,其中Git经验丰富的Dustin回答他自己的Git新手问题

事实上,他已经广泛地使用了这两种dvcss,并且对它们都有很好的理解——最终他更喜欢git。


最大的区别在于窗户。Mercurial是本机支持的,而Git不是。你可以通过bitback.org获得类似于github.com的托管(实际上,当你获得免费的私有存储库时,情况会更好)。我用msysgit有一段时间了,但我搬到了mercurial,并对此非常满意。


如果您是Windows开发人员,正在寻找基本的断开连接的修订控件,请使用hg。我发现Git是不可理解的,而Hg是简单的,并与Windows外壳很好地集成。我下载了hg并遵循了这个教程(hginit.com),十分钟后我有了一个本地的repo,并重新开始我的项目。


我认为对"mercurial vs.git"最好的描述是:

"吉特是韦斯利·斯奈普斯。摩科里亚尔是丹泽尔·华盛顿


它们几乎是相同的。从我的角度来看,最重要的区别(我的意思是,让我选择一个DVC而不是另一个)是两个程序如何管理分支。

要使用Mercurial启动一个新的分支,只需将存储库克隆到另一个目录并开始开发。然后,你拉合并。对于git,您必须显式地为要使用的新主题分支命名,然后使用相同的目录开始编码。

简而言之,Mercurial中的每个分支都需要自己的目录;在Git中,您通常在单个目录中工作。在mercurial中切换分支意味着更改目录;在git中,意味着要求git使用git checkout更改目录的内容。

我是诚实的:我不知道是否可以对mercurial做同样的事情,但是因为我通常在Web项目上工作,所以对Git使用相同的目录对我来说似乎很方便,因为我不必重新配置Apache并重新启动它,而且每次分支时我也不会弄乱文件系统。

编辑:正如Deestan所指出的,hg已经命名了分支,这些分支可以存储在单个存储库中,并允许开发人员在同一个工作副本中切换分支。无论如何,git分支与mercurial命名的分支并不完全相同:它们是永久性的,不会像git那样丢弃分支。这意味着,如果将命名分支用于实验任务,即使您决定永远不合并它,它也将存储在存储库中。这就是为什么hg鼓励将克隆用于实验性的、短时间运行的任务,并将命名的分支用于长时间运行的任务,比如发布分支。

很多hg用户喜欢克隆而不是命名分支的原因是,它比技术更具社会性或文化性。例如,对于hg的最后一个版本,甚至可以关闭一个命名的分支并递归地从变更集中删除元数据。

另一方面,Git邀请使用"命名分支",这些分支不是永久性的,并且不会作为元数据存储在每个变更集中。

从我个人的观点来看,Git的模型与命名分支的概念有着深刻的联系,并且在具有相同目录的分支和另一个分支之间进行切换;hg可以对命名分支做同样的事情,但是它鼓励使用克隆,我个人并不太喜欢克隆。


Git和Mercurial之间有一个巨大的区别:它们代表每个提交的方式。Git将提交表示为快照,而Mercurial将提交表示为差异。

这在实践中意味着什么?在Git中,许多操作都更快,例如切换到另一个提交、比较提交等,特别是在这些提交距离很远的情况下。

阿法克的方法没有任何优势。


没有什么。他们都做同样的事,都表现得差不多。您应该选择其中一个而不是另一个的唯一原因是,如果您帮助一个已经使用了一个的项目。

选择其中一个的另一个可能原因是应用程序或服务只支持系统中的一个。例如,我几乎选择学习Git是因为Github。


还有谷歌的比较(虽然它有点旧,但在2008年就完成了)

http://code.google.com/p/support/wiki/dvcanalysis


如果我正确理解它们(而且我远不是每一个方面的专家),它们基本上都有不同的哲学。我第一次使用Mercurial是9个月。现在我用了6个Git。好的。

Hg是版本控制软件。它的主要目标是跟踪软件版本。好的。

Git是一个基于时间的文件系统。它的目标是向文件系统添加另一个维度。大多数都有文件和文件夹,Git增加了时间。作为一个风投,它恰巧表现得很棒,这是它设计的副产品。好的。

在hg中,有一个它一直试图维护的整个项目的历史。默认情况下,我认为hg希望所有用户在推和拉时对所有对象进行所有更改。好的。

在Git中,只有一个对象池和这些跟踪文件(分支/头),用于确定哪些对象集表示处于特定状态的文件树。当推或拉Git时,只发送您推或拉的特定分支所需的对象,这是所有对象的一个子集。好的。

就Git而言,没有"1个项目"。你可以在同一个回购中拥有50个项目,而Git不在乎。每一个都可以在同一个回购协议中单独管理,并且活得很好。好的。

Hg的分支概念是指主项目的分支或分支等。Git没有这样的概念。Git中的一个分支只是树的一个状态,所有东西都是Git中的一个分支。哪个分支是官方的、当前的或最新的,在Git中没有意义。好的。

我不知道这是否有道理。如果我能画出这样的图片,hg可能看起来像这样,每个提交都是一个o。好的。

1
2
3
4
5
             o---o---o
            /        
o---o---o---o---o---o---o---o
         \         /
          o---o---o

一棵只有一根和树枝的树。虽然Git可以做到这一点,而且人们经常以这种方式使用它,但这并不是强制执行的。一张Git图片,如果有这样的东西,很容易看起来像这样。好的。

1
2
3
4
5
6
7
o---o---o---o---o

o---o---o---o
         \
          o---o

o---o---o---o

事实上,在某些方面,用git显示分支甚至没有意义。好的。

对于讨论来说,有一点非常令人困惑,Git和Mercurial都有一个称为"分支"的东西,但它们并不是完全相同的东西。当不同回购协议之间存在冲突时,就会出现Mercurial的一个分支。Git中的一个分支显然类似于Hg中的一个克隆。但是克隆,虽然它可能会给出类似的行为,但绝大多数情况下是不一样的。考虑一下,我用铬回购,在Git和Hg中尝试这些,这是相当大的。好的。

1
2
3
4
5
6
$ time git checkout -b some-new-branch
Switched to new branch 'some-new-branch'

real   0m1.759s
user   0m1.596s
sys    0m0.144s

现在在hg中使用克隆好的。

1
2
3
4
5
6
7
$ time hg clone project/ some-clone/

updating to branch default
29387 files updated, 0 files merged, 0 files removed, 0 files unresolved.
real   0m58.196s
user   0m19.901s
sys    0m8.957

这两个都是热门话题。我跑了两次,这是第二次。hg clone实际上与git new workdir相同。这两个目录都是一个全新的工作目录,几乎就像你输入了cp -r project project-clone一样。这与在Git创建新分支不同。它的重量要重得多。如果在hg中确实有Git分支的等价物,我不知道它是什么。好的。

我知道在某种程度上,hg和git可能会做类似的事情。如果是这样,那么在他们引导您进入的工作流中仍然存在巨大的差异。在Git中,典型的工作流是为每个特性创建一个分支。好的。

1
2
3
4
5
6
git checkout master
git checkout -b add-2nd-joypad-support
git checkout master
git checkout -b fix-game-save-bug
git checkout master
git checkout -b add-a-star-support

它只创建了3个分支,每个分支都基于一个名为master的分支。(我相信在Git中有一些方法可以使每行1行而不是2行)好的。

现在我只想做一个好的。

1
git checkout fix-game-save-bug

开始工作。提交事务等。即使在像chrome这样大的项目中,分支之间的切换也几乎是即时的。我真的不知道如何在hg中做到这一点。这不是我读过的任何教程的一部分。好的。

还有一个很大的区别。吉特的舞台。好的。

Git有一个舞台的想法。你可以把它当作一个隐藏的文件夹。当您提交时,只提交阶段上的内容,而不提交工作树中的更改。听起来可能很奇怪。如果要提交工作树中的所有更改,可以执行git commit -a,它将所有修改过的文件添加到该阶段,然后提交它们。好的。

那舞台有什么意义呢?你可以很容易地分开你的承诺。假设您编辑了joypad.cpp和gamesave.cpp,并且希望分别提交它们好的。

1
2
3
4
git add joypad.cpp  // copies to stage
git commit -m"added 2nd joypad support"
git add gamesave.cpp  // copies to stage
git commit -m"fixed game save bug"

Git甚至有命令来决定要复制到该阶段的同一个文件中的哪些特定行,这样您也可以将这些提交分开。你为什么要这么做?因为作为单独的提交,其他人只能提取他们想要的提交,或者如果存在问题,他们可以只恢复有问题的提交。好的。好啊。


在VersionControlBlog上有一个动态比较图,您可以在其中比较几个不同的版本控制系统。

这是Git、Hg和BZr的比较表。


您的项目中是否有基于Windows的合作者?

因为如果有的话,Git for Windows图形用户界面就显得笨拙、困难、不友好。

相比之下,Windows上的Mercurial则是一个轻而易举的选择。


在bitback.org的mercurial和github的git之间需要注意的一点是,mercurial可以拥有任意多的私有存储库,但是github必须升级到付费帐户。所以,这就是为什么我选择使用mercurial的bitbacke。


在与分支机构(尤其是短期分支机构)合作时,存在相当大的差异。

本文(BranchingExplained)解释了将Mercurial与Git进行比较的原因。


去年的某个时候,我对Git和Hg进行了评估,并决定使用Hg。我觉得它看起来是一个更清洁的解决方案,并且在更多的平台上工作得更好。不过,这基本上是一个折腾。

最近,我开始使用Git是因为Git SVN和充当颠覆客户机的能力。这赢了我,我现在完全转向了Git。我认为它有一个稍高的学习曲线(特别是如果你需要深入了解内部),但它确实是一个很好的系统。我要去读约翰现在发表的那两篇比较文章。


我目前正在从SVN迁移到DVC的过程中(在写关于我的发现的博客时,我第一次真正的博客工作…),我做了一些研究(=谷歌)。据我所知,你可以用这两个软件包做大部分事情。似乎Git有一些更多或更好的高级功能,我确实觉得与Windows的集成对于Mercurial和TortoiseHg有点好。我知道还有Git Cheetah(我试过两种方法),但Mercurial解决方案感觉更强大。

看看他们都是开源的(对吧?)我认为两者都不会缺少重要的特性。如果某件事很重要,人们会要求它,人们会对它进行编码。

我认为对于常见的实践来说,git和mercurial已经足够了。他们都有使用它们的大项目(GIT-Linux内核,Myalial-Mozilla基金会项目,当然还有其他两个项目),所以我不认为两者都真的缺少什么。

也就是说,我对其他人对这一点的看法很感兴趣,因为这将成为我写博客努力的一个很好的来源;—)


在InfoQ关于DVC的指南中,有一个关于Git、Mercurial和Bazaar的非常详尽的比较表和图表。


我意识到这不是答案的一部分,但在这个问题上,我也认为对于NetBeans和Eclipse这样的平台,稳定插件的可用性起到了一个作用,即工具更适合任务,或者更确切地说,哪个工具最适合"你"。也就是说,除非你真的想用cli的方式来做。

Eclipse(以及基于它的所有东西)和Netbean有时在远程文件系统(如ssh)和文件的外部更新方面都会出现问题;这也是您希望任何选择都"无缝"工作的另一个原因。

我也在试着自己回答这个问题。我已经把候选人分解成Git或Mercurial。感谢大家在不信教的情况下提供关于这个主题的有用信息。


如果您对Mercurial和Git的性能比较感兴趣,请看本文。结论是:

Git and Mercurial both turn in good numbers but make an interesting trade-off between speed and repository size. Mercurial is fast with both adds and modifications, and keeps repository growth under control at the same time. Git is also fast, but its repository grows very quickly with modified files until you repack — and those repacks can be very slow. But the packed repository is much smaller than Mercurial's.


还有一个有趣的关于Mercurial和Git的比较:Mercurial和Git。主要关注内部及其对分支过程的影响。


反复无常的网站对这两个系统的异同进行了大量的描述,解释了词汇和基本概念的不同。作为一个长期的Git用户,它确实帮助我理解了反复无常的心态。


如果要从SVN迁移,请使用mercurial,因为SVN用户更容易理解它的语法。除此之外,你也不能出错。但是在选择其中一个之前,一定要检查git教程和hgint。


有些人认为VCS系统一定很复杂。他们鼓励在这个领域发明术语和概念。他们可能会认为许多关于这个问题的博士学位会很有趣。其中可能是设计Git的。

Mercurial的设计理念不同。开发人员不应该太关心VCS,他们应该把时间花在他们的主要功能上:软件工程。Mercurial允许用户使用并愉快地滥用系统,而不允许他们犯任何不可恢复的错误。

任何专业工具都必须具有清晰设计和直观的CLI。Mercurial用户可以通过发出简单的命令来完成大部分工作,而不需要任何奇怪的选项。在Git Double Dash中,疯狂的选择是常态。如果您是一名CLI人员,那么Mercurial有很大的优势(老实说,任何有自尊心的软件工程师都应该是这样)。

举个例子,假设你犯了一个错误。你忘了编辑一些文件。要在Mercurial中撤消操作,只需键入:

$ hg rollback

然后,您会收到一条消息,说明系统撤消了上一个事务。

在Git中,您必须键入:

江户十一〔一〕号

好吧,假设你知道什么是重置。但除此之外,你还必须知道什么是"软"和"硬"重置(有什么直观的猜测吗?)哦,当然,最后别忘了^'这个角色!(现在里奇的名字是…)

Mercurial与第三方工具(如kdiff3和meld)的集成也更好。生成你的补丁合并你的分支没有太多麻烦。Mercurial还包括一个简单的HTTP服务器,您可以通过键入

埃多克斯1〔2〕

让其他人浏览您的存储库。

归根结底,Git做的和Mercurial做的一样,以一种更加复杂的方式,使用一个非常差的CLI。如果你想把你项目的风投变成一个科学研究领域,可以使用git。如果你想在不太关心的情况下完成VCS的工作,那么就使用mercurial,并专注于你真正的任务。


此链接可以帮助您了解差异http://www.techtatava.com/2010/09/git-mercurial-and-bazaar-a-比较/