Mercurial和Git有什么区别?


727

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

有没有人在git和hg之间进行并排比较?我有兴趣知道hg和git的不同之处,而不必参加狂热的讨论。

Answers:



238

我从事Mercurial的工作,但从根本上来说,我认为这两个系统是等效的。它们都使用相同的抽象:构成历史的一系列快照(变更集)。每个变更集都知道其来源(父变更集),并且可以具有许多子变更集。最近的hg-git扩展在Mercurial和Git之间提供了一条双向桥梁,并显示了这一点。

Git十分注重更改此历史记录图(及其带来的所有后果),而Mercurial并不鼓励重写历史记录,但是无论如何都很容易做到,这样做的后果正是您应该期望的(即,如果我修改了您已经拥有的变更集,那么从我这里撤消后,您的客户就会将其视为新的变更集。因此,Mercurial 对无损命令有偏见

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

我使用Linux,但显然TortoiseHg比Windows上的Git等效更快和更好(由于更好地使用了不良的Windows文件系统)。无论http://github.comhttp://bitbucket.org提供在线托管,在到位桶的服务是伟大的,响应的(我没有尝试过的github)。

我选择Mercurial是因为它干净利落-我对Git附带的shell / Perl / Ruby脚本不满意。如果您想了解我的意思,请尝试看一下该git-instaweb.sh文件:这是一个生成Ruby脚本的Shell脚本,我认为该脚本运行Web服务器。Shell脚本生成另一个Shell脚本以启动第一个Ruby脚本。还有一点Perl,很好。

我喜欢将Mercurial和Git与James Bond和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在我看来更加优雅。


21
请注意,TortoiseHg还可以与Linux上的Gnome文件管理器Nautilus一起使用。
oenli 2010年

4
仅当httpd是Webrick(ruby Web服务器)时,才会生成Ruby脚本。
替代

4
与Git一样,Mercurial在提交时会存储文件的快照。我不同意只能使用Git中的启发式方法来跟踪重命名,模型中没有任何东西可以阻止向快照添加额外的信息,例如重命名信息。我们在Mercurial中做到这一点。
Martin Geisler

63
要将不相关的项目与git合并(拉),您可以执行以下操作:git pull <url-of-project>。你报的邮件是从混帐的非常初期(2005年)
knittl

5
knittl:啊,很好,很高兴听到Git变得越来越不可思议。尽管如此,我认为该示例仍显示出一些系统在我们认为凉爽的系统方面有何不同,并且与Mercurial相比,Git对我来说更底层(但没有任何更强大的功能)。
马丁·盖斯勒

73

Git是一个平台,Mercurial是“仅”一个应用程序。Git是一个版本化的文件系统平台,刚好随附了DVCS应用程序,但与平台应用程序一样,它比集中应用程序更复杂且边缘更粗糙。但这也意味着git的VCS非常灵活,并且您可以使用git进行大量的非源代码控制。

这就是差异的本质。

从根本上最好地了解Git –从存储库格式开始。Scott Chacon的Git Talk是对此的出色入门。如果您尝试使用git而不了解幕后发生的事情,那么您最终会在某些时候感到困惑(除非您仅坚持非常基本的功能)。当您想要的只是日常编程例程的DVCS时,这听起来可能很愚蠢,但是git的天才之处在于,存储库格式实际上非常简单,您可以很容易地理解git的整个操作。

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

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


78
我经常阅读人们提到git是一个“平台”,但这更多是一种理论或普遍的神话,因为除了运行git之外,没有其他主要示例将其用作执行其他操作的平台。
伊恩·凯灵

@Ian-如果我没有记错的话,Aptana Studio 3会将其用于其内部更新系统。
mac

22
因此,简而言之:Mercurial是一个开源的分布式修订控制系统,而git是一种生活方式选择。
Tim Keating

51

最大的区别在于Windows。Mercurial本身受支持,而Git则不受支持。您可以使用bitbucket.org获得与github.com非常相似的托管服务(实际上,获得免费的私有存储库甚至更好)。我使用msysGit已有一段时间,但后来搬到Mercurial并对此感到非常满意。


64
因此,“本地”不是一个正确的词,但可以肯定的是,在Windows下它并没有得到很好的支持。
伊恩·凯林

14
git在Windows上受支持。但是,尝试跨平台使用Unicode文件名,看看会遇到什么麻烦。
克雷格·麦昆

@Craig:更多的是平台缺陷。一个称职的平台将允许您切换到合适的区域。如果您坚持使用utf-8,除了Mac OS X的utf-8规范化略有不同外,其他都可以,但是,我不确定Windows是否允许您使用utf-8 ...
Arafangion

23
Windows支持Unicode,尽管MS选择在其API中使用UTF-16,而不是UTF-8。尽管如此,git有可能支持Unicode跨平台。SVN很好地解决了这个问题。但是,目前这对于msysGit开发来说并不是一个高度优先的事情。code.google.com/p/msysgit/issues/detail?id=80
Craig McQueen 2010年

38

如果您是Windows开发人员,正在寻找基本的脱机版本控制,请使用Hg。我发现Git难以理解,而Hg很简单,并且与Windows Shell很好地集成在一起。我下载了Hg,并按照了本教程(hginit.com)的操作 -十分钟后,我有了一个本地存储库,然后又可以开始进行我的项目了。


1
我遵循了相同的教程。是确定的。
弥敦道


20

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

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

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

老实说:我不知道是否可以对Mercurial进行同样的操作,但是由于我通常在Web项目上工作,因此对git使用始终相同的目录似乎很方便,因为我不必重新启动-配置Apache并重新启动它,并且每次分支时都不会弄乱文件系统。

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

许多Hg使用者偏爱克隆而不是命名分支的原因,其社会或文化意义远大于技术意义。例如,使用最新版本的Hg,甚至可以关闭命名分支并从变更集中递归删除元数据。

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

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


6
这没有什么区别;汞也命名了分支。在正常开发过程中,我们一直都在使用它们,而不是使用克隆分支。
Deestan

2
获得AFAIK(以Hg命名的分支),并在每次提交中存储元数据;我可能错了,但是我读到一旦创建分支,它的元数据将嵌入到每个变更集中,并成为历史的一部分。这与git有很大的区别。“克隆适用于不想记录分支名称的快速实验,而命名分支则适合长期分支。” tinyurl.com/2wz39qx 我在帖子中要说的是git的标准工作流程邀请您使用单个工作副本;汞标准工作流程包括克隆,这些克隆无法满足我的个人需求。
Arialdo Martini

有关以下内容的相似性/差异的良好解释:在Git和Hg中分支,请参阅:mercurial.selenic.com/wiki/GitConcepts#Branch_model
sampablokuper 2011年

2
hg中的命名分支与git中的分支完全不同。在汞中,有一条真实的道路。所有分支都是该路径的分支。在git中,没有一条真正的道路。存储库只有几种不同的状态,并且指针指向该状态。每个分支只是一个不同的指针。主要使用哪个指针。分支都是同级。
gman

17

gitmercurial之间有一个巨大的区别;表示每次提交的方式。git将提交表示为快照,而mercurial将其表示为diff。

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

AFAIK没有Mercurial的方法的优势。


29
变更集(差异)的优势在于占用更少的空间。Git通过使用压缩来恢复用于提交的空间,但这需要一个偶尔的显式重新压缩步骤(“ git pack”)。
夸克

8
现在它被称为“ git gc”,但是垃圾回收有不同的级别,并且某些级别在最新版本的git中自动执行。
FelipeC

6
实际上,Mercurial也使用快照
Ronny 2010年

13
我不明白您在“快照”和“差异”之间的区别。hg和git store都以文件deltas的形式提交。这些增量基于相应SCM选择的任何先前版本。您是否有数字表明git实际上对您提到的操作更快?无论如何,更新到另一个提交会花费大部分时间写入工作目录,而不是读取存储库。
凯文

2
“快照”与“差异”-完全无关。但是,回购存储在内部,与用户看到的内容无关。git和mercurial都向用户显示“快照”。没有理由不能像我相信Bazaar一样,将以与git相同的方式实现的存储库格式添加到mercurial中。
Mark Booth,

11

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

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


6
看来您的答案太实用了。:)
Arafangion 2010年


11

如果我正确地理解它们(并且我与每个专家都相距甚远),那么从根本上来说,每个人都有不同的哲学。我第一次使用水银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两者都有一个叫做“分支”的东西,这对于讨论来说非常令人困惑,但是它们并不是完全相同的。当不同的回购协议之间存在冲突时,就会产生分支。git中的分支显然类似于hg中的克隆。但是,尽管克隆可能会给出类似的行为,但绝对是不同的。考虑我使用相当大的铬仓库在git vs hg中尝试这些。

$ 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分支的等效项,我不知道它是什么。

我在一定程度上了解汞和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这样大的项目中,在分支之间切换也几乎是瞬时的。我实际上不知道如何在汞中做到这一点。它不是我已阅读的任何教程的一部分。

另一大不同。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甚至具有命令来决定要将同一文件中的哪些特定行复制到舞台,因此您也可以分别拆分这些提交。你为什么想这么做?因为作为单独的提交,其他人只能拉他们想要的提交,或者如果有问题,他们可以只还原出现问题的提交。


“ Git甚至具有命令来决定要将同一文件中的哪些特定行复制到舞台上,以便您也可以分别拆分那些提交。” 这些命令是什么?
James McMahon

1
@James:,git add --patch请参阅linux.die.net/man/1/git-add或使用git add -i,例如在stackoverflow.com/questions/2372583/…中
tanascius 2012年

@gman:您无需签出master并进行分支,而checkout -b <name>可以直接使用它git branch <name>来创建一个新分支,而无需切换到该分支
tanascius 2012年

8

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

这是git,hg和bzr之间的比较表。


1
关于Mercurial的信息并不完全准确:Mercurial确实具有“移动或重命名后的智能合并”。具体而言,这意味着,如果我重新命名dir-a/foo.cdir-b/foo.c并保持工作dir-b/foo.c,那么你的工作dir-a/foo.c将是正确的拉带后,我的工作合并。
马丁·盖斯勒

关于Git的信息(来自Better SCM Initiative比较,IIRC)在某些地方也不准确,甚至含糊不清。
JakubNarębski2010年


7

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

因为如果有的话,Windows的Git GUI似乎很笨拙,困难,不友好。

相比之下,Windows上的Mercurial无需理会。


我喜欢git,但是我必须在这里同意。Git在舞台上有一个更好的命令行,并且文档更好。我会在posix shell中愉快地使用git命令。但是Windows上的tortoiseHG很棒,它甚至与多个diff工具集成(超越比较),并且完全支持sub-repos,以及许多hg插件,如strip / mq
Keyo

至少有一个非常好的Windows(以及OS X + Linux)Git GUI。
蒙特

7

在bitbucket.org的mercurial和github的git之间需要注意的一件事是,mercurial可以具有任意数量的私有存储库,但是github您必须升级到付费帐户。因此,这就是为什么我会使用水银的位桶的原因。


5

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

最近,由于git-svn和充当Subversion客户端的功能,我开始使用git。这为我赢得了胜利,现在我完全切换到了git。我认为它的学习曲线稍高一些(特别是如果您需要深入研究的话),但这确实是一个很棒的系统。我将去阅读John现在发布的这两篇比较文章。


4
看一下hgsubversion:bitbucket.org/durin42/hgsubversion。目前,它需要开发版本的Mercurial,但是他们将发布Mercurial 1.3的版本,该版本将于7月1日发布。
马丁·盖斯勒

4

我目前正在从SVN迁移到DVCS的过程中(在写博客时,我的发现是我第一次真正的写博客的努力……),并且我已经做了一些研究(=搜索)。据我所知,您可以使用这两个软件包完成大多数操作。似乎git具有更多或更好地实现的高级功能,我确实感觉到与Windows集成对于使用TortoiseHg的软件来说要好一些。我知道也有Git Cheetah(我都尝试过),但是这种商品解决方案感觉更强大。

看到它们都是开源的(对吗?),我认为它们都不会缺少重要的功能。如果重要的事情,人们会要求它,人们会编写代码。

我认为,对于常规做法,Git和Mercurial绰绰有余。他们两个都有使用它们的大型项目(Git-> linux内核,Mercurial-> Mozilla基础项目,当然还有其他两个项目),因此我不认为它们确实缺少任何东西。

话虽这么说,我对其他人对此的看法很感兴趣,因为它将为我的博客工作提供重要的资源;-)


1
是的,它们都是开源项目。
马丁·盖斯勒


3

我意识到这不是答案的一部分,但在那一点上,我还认为针对NetBeans和Eclipse等平台的稳定插件的可用性在其中哪个工具更适合该任务,或者说哪个工具更重要。最适合“你”。也就是说,除非您真的想通过CLI方式进行操作。

Eclipse(以及所有基于它的东西)和NetBeans有时在远程文件系统(例如SSH)和文件的外部更新方面都存在问题。这就是为什么您希望自己选择的任何东西都能“无缝”工作的另一个原因。

我现在也正试图为我自己回答这个问题..我已经将候选人归结为Git或Mercurial ..谢谢大家在不信奉宗教的情况下提供了关于该主题的有用信息。


2
+1,因为“无缝”体验比不使用这些东西的人认为更重要。IDE的可靠插件具有很大的不同。
eksortso,2010年


2

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

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



2

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



1

有人认为VCS系统必须很复杂。他们鼓励在现场发明术语和概念。他们可能会认为,有关该主题的众多博士学位会很有趣。其中可能是设计Git的那些。

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

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

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

$ hg rollback

然后,您会收到一条消息,提示系统撤消您上一次的交易。

在Git中,您必须输入:

$ git reset --soft HEAD^

好吧,假设您知道复位的含义。但是除此之外,您还必须知道什么是“-软”和“-硬”重置(任何直观的猜测?)。哦,当然不要忘了最后的'^'字符!(现在以里奇的名义...)

Mercurial与第三方工具kdiff3和meld的集成也要好得多。生成补丁可以合并分支,而不必大惊小怪。Mercurial还包括一个简单的http服务器,您可以通过键入以下内容来激活它

hg serve

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

最重要的是,Git以更复杂的方式并且以劣等的CLI来完成Mercurial的工作。如果要将项目的VCS变成科学研究领域,请使用Git。如果您想完成VCS任务而不关心它,请使用Mercurial,并专注于实际任务。


1
实际上,您可以在git中为命令添加别名,这使得CLI的使用更加简单。这个SuperUser(StackExchange)问题中有很多
Spoike 2012年

1
确实是的,您还可以编写Shell脚本来处理一些常见任务。最终,您开始意识到,您正在构建一个包装器CLI,以处理具有错误设计和违反直觉的CLI的VCS。不仅如此。Git引入了许多概念,这些概念的可用性令人质疑,最终使用户不得不学习和理解,以便对文档和CLI消息感到满意。
Kostas 2012年
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.