Mercurial和Git有什么区别?

我已经在Windows上使用git一段时间了(使用msysGit),我喜欢分布式源代码控制的想法。就在最近,我一直在研究Mercurial(hg),它看起来很有趣。然而,我无法理解hg和git之间的区别。

有人在git和hg之间做过并排比较吗?我很想知道hg和git有什么不同,而不必跳进粉丝讨论。

641778 次浏览

我目前正在从SVN迁移到DVCS(同时写博客讲述我的发现,我第一次真正的博客努力……),我做了一些研究(=谷歌搜索)。据我所知,你可以用这两个包做大部分的事情。似乎git有一些更多或更好的高级功能, 我确实觉得与Windows的集成对于Mercurial来说要好一点,使用TortoiseHg。我知道还有Git Cheetah(我试了两个),但是mercurial解决方案感觉更强大。

看到它们都是开源的(对吧?)我认为两者都不会缺乏重要的功能。如果某件事很重要,人们会要求它,人们会编写代码。

我认为对于常见的实践,Git和Mercurial已经足够了。他们都有使用它们的大项目(Git->linux内核,Mercurial->Mozilla基础项目,当然还有其他),所以我认为两者都没有真正缺乏什么。

话虽如此,我对其他人对此的看法很感兴趣,因为它将为我的博客努力提供一个很好的来源;-)

这些文章可能有助于:

编辑:将Git和Mercurial比作名人似乎是一种趋势。这里还有一个:

  • 去年的某个时候,我评估了git和hg供我自己使用,并决定使用hg。我觉得它看起来像一个更清洁的解决方案,并且在当时在更多平台上运行得更好。不过,这主要是一个折腾。

    最近,我开始使用git,因为git-svn和充当Subversion客户端的能力。这赢得了我,我现在已经完全切换到git。我认为它的学习曲线略高(特别是如果你需要深入了解内部),但它确实是一个很棒的系统。我要去阅读John现在发布的那两篇比较文章。

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

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

InfoQ关于DVCS的指南上有一个关于git、Mercurial和Bazaar的出色而详尽的比较表格和图表。

最大的区别是在Windows上。Mercurial是原生支持的,Git不是。你可以用bitbucket.org获得与github.com非常相似的托管(实际上,当你获得免费的私有存储库时甚至更好)。我使用msysGit一段时间,但转移到Mercurial并对它非常满意。

Git是一个平台,Mercurial“只是”一个应用程序。Git是一个版本化的文件系统平台,碰巧在盒子里附带了一个DVCS应用程序,但作为平台应用程序的正常情况,它比专注应用程序更复杂,边缘更粗糙。但这也意味着git的VCS非常灵活,并且你可以用git做大量的非源代码控制事情。

这就是区别的本质。

最好从头开始理解Git——从存储库格式开始。Scott Chacon的Git Talk是一个很好的入门。如果你试图使用git而不知道底层发生了什么,你最终会在某个时候感到困惑(除非你只坚持非常基本的功能)。当你只想要一个用于日常编程的DVCS时,这听起来可能很愚蠢,但git的天才在于存储库格式实际上非常简单,你可以很容易理解git的整个操作。

对于一些更具技术性的比较,我个人看到的最好的文章是达斯汀·萨林斯的:

他实际上已经广泛使用了这两种DVCS,并且对它们都很了解-最终更喜欢git。

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

这是git、hg和bzr之间的对照表。

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

我认为关于“Mercurial vs. Git”的最佳描述是:

"Git是Wesley Snipes. Mercurial是Denzel Washington""Git是Wesley Snipes. Mercurial是Denzel Washington"

我在Mercurial上工作,但从根本上我相信两个系统是等价的。它们都使用相同的抽象:构成历史的一系列快照(变更集)。每个变更集知道它来自哪里(父变更集)并且可以有许多子变更集。最近的hg-git扩展在Mercurial和Git之间提供了一个双向桥梁,并在某种程度上说明了这一点。

Git非常专注于改变这个历史图(以及随之而来的所有后果),而Mercurial不鼓励重写历史,但这很容易做到和这样做的后果正是你应该期待的(也就是说,如果我修改了你已经拥有的更改集,如果你从我这里拉出来,你的客户会认为它是新的)。所以Mercurial对非破坏性命令有一个偏见

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

我使用Linux,但显然TortoiseHg比Windows上的Git更快更好(由于更好地使用了糟糕的Windows文件系统)。http://github.comhttp://bitbucket.org都提供在线托管,BitBay的服务很棒且响应迅速(我没有尝试过github)。

我选择了Mercurial,因为它感觉干净优雅——我被Git的shell/Perl/Ruby脚本推迟了。如果你想知道我的意思,试着看一眼git-instaweb.sh文件:它是一个shell脚本,它生成一个ruby脚本,我认为它运行一个网络服务器。脚本外壳生成另一个外壳脚本来启动第一个Ruby脚本。还有一点perl,很好的衡量标准。

我喜欢博客文章,它将Mercurial和Git与詹姆斯·邦德和MacGyver进行了比较——Mercurial在某种程度上比Git更低调。在我看来,使用Mercurial的人并不容易留下深刻印象。这反映在每个系统如何执行Linus所描述的“有史以来最酷的合并!”上。在Git中,您可以通过以下操作与不相关的存储库合并:

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中,我们这样做:

hg pull --force <project-to-union-merge>
hg merge
hg commit

请注意Mercurial命令是多么简单,一点也不特别——唯一不寻常的是--force标志到hg pull,这是必要的,因为当您从不相关的存储库中提取时,Mercurial会中止。正是这样的差异使Mercurial对我来说看起来更优雅。

git水银之间有一个巨大区别;表示每个提交的方式。git将提交表示为快照,而水银将它们表示为差异。

这在实践中意味着什么?好吧,许多操作在git中更快,例如切换到另一个提交、比较提交等。特别是如果这些提交很远。

AFAIK没有Mercurial的方法的优势。

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

它在这篇文章(分支解释)中解释,它将Mercurial与Git进行比较。

还有谷歌的比较(虽然有点老了,2008年完成)

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

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

Git和Mercurial都取得了不错的成绩,但在速度和存储库大小之间进行了有趣的权衡。Mercurial在添加和修改方面都很快,同时可以控制存储库的增长。Git也很快,但它的存储库随着修改的文件而增长得非常快,直到你重新打包——而这些重新打包可能很慢。但是打包的存储库比Mercurial的小得多。

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

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

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

老实说:我不知道是否可以用Mercurial做同样的事情,但由于我通常从事Web项目,使用git总是相同的目录对我来说似乎很舒服,因为我不必重新配置Apache并重新启动它,而且每次分支时我都不会弄乱我的文件系统。

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

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

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

从我个人的角度来看,git的模型与命名分支的概念紧密相连,并在同一目录的分支和另一个分支之间切换;hg可以对命名分支做同样的事情,但它鼓励使用克隆,我个人不太喜欢。

我知道这不是答案的一部分,但在这一点上,我也认为NetBeans和Eclipse等平台的稳定插件的可用性在哪个工具更适合这项任务中发挥了作用,或者更确切地说,哪个工具最适合“你”。也就是说,除非你真的想以CLI的方式来做。

Eclipse(以及基于它的一切)和NetBeans有时都存在远程文件系统(例如SSH)和文件外部更新的问题;这也是您希望无论您选择什么都能“无缝”工作的另一个原因。

我现在也在为自己回答这个问题……我已经把候选人归结为Git或Mercurial……感谢大家在这个话题上提供有用的输入,而不是宗教信仰。

如果你是一个寻找基本的断开连接版本控制的Windows开发人员,请使用Hg。我发现Git难以理解,而Hg很简单并且与Windows shell很好地集成。我下载了Hg并关注本教程(hginit.com)-十分钟后,我有了一个本地存储库并回到了我的项目中。

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

因为如果有,Git-for-Windows GUI看起来很尴尬、困难、不友好。

相比之下,Mercurial-on-Windows是一个简单的选择。

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

mercurial网站在两个系统之间有一个对异同的很好描述,解释了词汇和底层概念的差异。作为一个长期的git用户,它确实帮助我理解了Mercurial的心态。

如果你是从SVN迁移的,请使用Mercurial,因为它的语法对于SVN用户来说更容易理解。除此之外,你也不会出错。但是在选择其中之一之前,请检查git教程HGinit

如果我对它们的理解是正确的(我远非每个方面的专家),它们从根本上每个都有不同的哲学。我第一次使用mercurial 9个月。现在我已经使用git 6个月了。

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

git是一个基于时间的文件系统。它的目标是为文件系统添加另一个维度。大多数都有文件和文件夹,git增加了时间。作为VCS,它碰巧工作得很棒,这是它设计的副产品。

在hg中,它总是试图维护整个项目的历史记录。默认情况下,我相信hg希望所有用户在推和拉时对所有对象进行所有更改。

在git中,只有一个对象池和这些跟踪文件(分支/头),它们决定了这些对象中的哪一组代表了处于特定状态的文件树。当推或拉git只发送你正在推或拉的特定分支所需的对象,这是所有对象的一小部分。

就git而言,没有“1个项目”。你可以在同一个仓库中有50个项目,git不会在意。每个项目都可以在同一个仓库中单独管理,生活得很好。

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

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

             o---o---o
/
o---o---o---o---o---o---o---o
\         /
o---o---o

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

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


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


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

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

有一件事在讨论中非常令人困惑,git和mercurial都有一个叫做“分支”的东西,但它们不是完全相同的东西。当不同的仓库之间存在冲突时,就会出现mercurial中的分支。git中的分支显然与hg中的克隆相似。但是克隆,虽然它可能会给出类似的行为,但绝对是不一样的。考虑一下我在git和hg中使用相当大的chromium仓库尝试这些。

$ time git checkout -b some-new-branch
Switched to new branch 'some-new-branch'


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

现在在HG中使用克隆

$ 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中,典型的工作流程是为每个功能创建一个分支。

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行)

现在来做一个我刚做的

git checkout fix-game-save-bug

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

另一个很大的区别。Git的舞台。

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

那么阶段的意义是什么呢?你可以很容易地分开提交。假设你编辑了joypad.cpp和gamesave.cpp,你想分别提交它们

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甚至有命令来决定要将同一文件中的哪些特定行复制到阶段,以便您也可以单独拆分这些提交。为什么要这样做?因为作为单独的提交,其他人只能提取他们想要的,或者如果有问题,他们可以只恢复有问题的提交。

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

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

任何专业工具都必须带有设计清晰且直观的CLI。Mercurial用户可以通过发出简单的命令来完成大部分工作,而无需任何奇怪的选项。在Git双破折号中,疯狂的选项是常态。如果你是CLI人(说实话,任何有自尊的软件工程师都应该是),Mercurial具有很大的优势。

举个例子,假设您错误地进行了提交。您忘记编辑一些文件。要在Mercurial中撤消您的操作,您只需键入:

$ hg rollback

然后,您会收到一条消息,系统撤消了您的上一笔交易。

在Git中,您必须输入:

$ git reset --soft HEAD^

所以好吧,假设你知道重置是关于什么的。但除此之外,你还必须知道“-soft”和“-hard”重置是什么(任何直觉猜测?)。哦,当然最后不要忘记'^'字符!(现在里奇的名字是什么…)

Mercurial与第3方工具(如kdiv3和meld)的集成也更好。生成您的补丁合并您的分支而无需大惊小怪。Mercurial还包括一个简单的超文本传输协议服务器,您可以通过键入来激活

hg serve

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

底线是,Git做了Mercurial所做的事情,方式要复杂得多,CLI也差得多。如果你想把项目的VCS变成一个科研领域,请使用Git。如果你想在不太关心VCS的情况下完成VCS工作,请使用Mercurial,并专注于你的实际任务。