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

有人把git和hg放在一起比较吗?我很想知道hg和git有什么不同,而不需要加入粉丝的讨论。


I'm currently in the process of migrating from SVN to a DVCS (while blogging about my findings, my first real blogging effort...), and I've done a bit of research (=googling). As far as I can see you can do most of the things with both packages. It seems like git has a few more or better implemented advanced features, I do feel that the integration with windows is a bit better for mercurial, with TortoiseHg. I know there's Git Cheetah as well (I tried both), but the mercurial solution just feels more robust.

因为它们都是开源的(对吧?)我认为这两款游戏都不会缺少重要的功能。如果某样东西很重要,人们就会提出要求,就会编写代码。

我认为对于常见的实践,Git和Mercurial已经足够了。它们都有使用它们的大型项目(Git -> linux内核,Mercurial -> Mozilla基金会项目,当然都在其他项目中),所以我不认为它们真的缺少什么。

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

以下文章可能会有所帮助:

Git vs Mercurial:请放松(Git是百战天龙,Mercurial是詹姆斯·邦德) Mercurial和Git的区别

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

Git是Wesley Snipes, Mercurial是Denzel Washington

去年的某个时候,我评估了git和hg供我自己使用,并决定使用hg。我觉得它看起来是一个更干净的解决方案,并且在更多的平台上工作得更好。不过,这基本上是一个未知数。

最近,我开始使用git,因为git-svn和充当Subversion客户端的能力。这征服了我,现在我完全换成了git。我认为它的学习曲线略高(特别是当你需要探究内部时),但它确实是一个很棒的系统。我要去读约翰发表的那两篇比较文章。

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

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

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

最大的不同在于Windows系统。Mercurial是本地支持的,Git不支持。你可以通过bitbucket.org获得与github.com非常相似的托管(实际上更好,因为你得到了一个免费的私有存储库)。我曾经使用过一段时间的msysGit,但后来转到Mercurial,我对它非常满意。

Git是一个平台,Mercurial“只是”一个应用程序。Git是一个版本控制的文件系统平台,附带了一个DVCS应用程序,但与平台应用程序一样,它比集中的应用程序更复杂,也更粗糙。但这也意味着git的VCS非常灵活,你可以用git做大量非源代码控制的事情。

这就是区别的本质。

Git is best understood from the ground up – from the repository format up. Scott Chacon’s Git Talk is an excellent primer for this. If you try to use git without knowing what’s happening under the hood, you’ll end up confused at some point (unless you stick to only very basic functionality). This may sound stupid when all you want is a DVCS for your daily programming routine, but the genius of git is that the repository format is actually very simple and you can understand git’s entire operation quite easily.

对于一些更偏向技术的比较,我个人看过的最好的文章是Dustin Sallings的:

Mercurial和Git的区别 Reddit上有经验丰富的达斯汀回答他自己的新手问题的帖子

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

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

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

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

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

“Git是韦斯利·斯奈普斯。Mercurial是丹泽尔·华盛顿

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

Git非常注重改变这个历史图(以及由此产生的所有后果),而Mercurial不鼓励重写历史,但这很容易做到,而且这样做的后果正是您应该期望的(也就是说,如果我修改了您已经拥有的变更集,如果您从我这里提取,您的客户端将会认为它是新的)。所以Mercurial偏向于非破坏性命令。

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

我使用Linux,但显然TortoiseHg在Windows上比Git更快更好(由于更好地使用了糟糕的Windows文件系统)。http://github.com和http://bitbucket.org都提供在线托管,Bitbucket的服务很棒,响应迅速(我还没有尝试过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中,你可以通过以下方式合并一个不相关的存储库:

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命令是多么简单,一点也不特殊——唯一不寻常的事情是hg拉取的——force标志,这是必需的,因为当您从不相关的存储库进行拉取时,Mercurial将中止。正是这样的差异使Mercurial在我看来更加优雅。

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

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

说真的,mercurial的方法没有任何优势。

当涉及到处理分支(特别是短期分支)时,有相当显著的差异。

本文(BranchingExplained)对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 checkout更改目录的内容。

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

Edit: As Deestan noted, Hg has named branches, which can be stored in a single repository and allow the developer to switch branches within the same working copy. git branches are not exactly the same as Mercurial named branches, anyway: they are permanent and not throw away branches, like in git. That means that if you use a named branch for experimental tasks even if you decide to never merge it it will be stored in the repository. That's the reason why Hg encourages to use clones for experimental, short-running tasks and named branches for long-running tasks, like for release branches.

为什么许多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就显得笨拙、困难、不友好了。

相比之下,“windows上的水银”则是显而易见的。

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

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

如果从SVN迁移,请使用Mercurial,因为它的语法对SVN用户来说更容易理解。除此之外,任何一种选择都不会错。但是在选择之前一定要检查GIT教程和HGinit。

如果我理解正确的话(我在这方面远远不是专家),它们基本上都有不同的哲学。我第一次使用mercurial有9个月。现在我用git表示6。

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

Git是一个基于时间的文件系统。它的目标是向文件系统添加另一个维度。大多数都有文件和文件夹,git增加了时间。作为一个风投公司,它的设计是一个副产品。

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

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

就git而言,不存在“1个项目”。你可以在同一个回购中有50个项目,git不会在意。每一个都可以在同一个回购和live fine中单独管理。

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

我不知道这是否有意义。如果我能把hg画出来,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都有一个叫做“分支”的东西,但它们并不是完全相同的东西。当不同的repo之间存在冲突时,mercurial就会产生一个分支。git中的分支显然类似于hg中的克隆。但是克隆虽然可能会给出类似的行为,但绝对不相同。考虑我尝试这些在git和hg使用铬repo相当大。

$ 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的克隆其实和git-new-workdir是一样的。这两个都创建了一个全新的工作目录,几乎就像输入cp -r project project-clone一样。这与在git中创建一个新分支不同。它的重量要重得多。如果git在hg中有分支,我不知道它是什么。

我知道在某种程度上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中有一些方法可以使每一行而不是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甚至有命令来决定要将同一文件中的哪些特定行复制到舞台,这样您也可以将这些提交分开。你为什么要这么做?因为作为单独的提交,其他人只能提取他们想要的,或者如果有问题,他们可以只恢复有问题的提交。

这个链接可以帮助你理解其中的区别 http://www.techtatva.com/2010/09/git-mercurial-and-bazaar-a-comparison/

有些人认为VCS系统必须是复杂的。他们鼓励在这个领域发明术语和概念。他们可能会认为这个领域的众多博士会很有趣。其中可能就是那些设计Git的人。

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

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

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

$ hg回滚

然后,您将收到一条消息,系统将撤销您的上一个事务。

在Git中,你必须输入:

$ git重置-软头^

假设你知道什么是重置。但除此之外,你还必须知道“软”和“硬”重置是什么(有什么直观的猜测吗?)哦,当然,不要忘记最后的'^'字符!(以里奇的名义……)

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

hg服务

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

归根结底,Git做了Mercurial做的事情,但方式要复杂得多,使用的CLI也差得多。如果您想将项目的VCS转换为科学研究领域,请使用Git。如果您希望在不太关心的情况下完成VCS工作,并专注于您的实际任务,请使用Mercurial。