我在 Windows(使用 msysGit)上使用 git 已经有一段时间了,我喜欢分布式源代码控制的想法。就在最近,我一直在看 Mercurial (hg),它看起来很有趣。但是,我无法理解 hg 和 git 之间的差异。
有没有人在 git 和 hg 之间进行并排比较?我很想知道 hg 和 git 有什么不同,而不必参加狂热的讨论。
我在 Windows(使用 msysGit)上使用 git 已经有一段时间了,我喜欢分布式源代码控制的想法。就在最近,我一直在看 Mercurial (hg),它看起来很有趣。但是,我无法理解 hg 和 git 之间的差异。
有没有人在 git 和 hg 之间进行并排比较?我很想知道 hg 和 git 有什么不同,而不必参加狂热的讨论。
这些文章可能会有所帮助:
编辑:将 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://bitbucket.org都提供在线托管,Bitbucket 的服务很棒而且响应迅速(我没有尝试过 github)。
我选择 Mercurial 是因为它感觉干净优雅——我对使用 Git 获得的 shell/Perl/Ruby 脚本感到厌烦。如果您想知道我的意思,请尝试查看该git-instaweb.sh
文件:它是一个生成Ruby脚本的shell脚本,我认为它运行一个网络服务器。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
标志 to hg pull
,这是必需的,因为当您从不相关的存储库中提取时,Mercurial 将中止。正是这样的差异让 Mercurial 在我看来更加优雅。
Git 是一个平台,Mercurial 只是一个应用程序。Git 是一个版本化的文件系统平台,它恰好附带一个 DVCS 应用程序,但与平台应用程序一样,它比专注的应用程序更复杂且边缘更粗糙。但这也意味着 git 的 VCS 非常灵活,并且您可以使用 git 做大量非源代码控制的事情。
这就是区别的本质。
最好从头开始理解 Git——从存储库格式开始。Scott Chacon 的 Git Talk是一个很好的入门教程。如果您在不知道幕后发生的情况下尝试使用 git,您最终会感到困惑(除非您只坚持非常基本的功能)。当您想要的只是日常编程例程的 DVCS 时,这听起来可能很愚蠢,但 git 的天才之处在于存储库格式实际上非常简单,您可以很容易地理解 git 的整个操作。
对于一些更注重技术性的比较,我个人看过的最好的文章是 Dustin Sallings 的:
他实际上已经广泛使用了这两种 DVCS,并且对它们都非常了解——最终他更喜欢 git。
最大的区别在于 Windows。Mercurial 是本机支持的,Git 不支持。您可以通过bitbucket.org获得与github.com非常相似的托管(实际上,当您获得免费的私有存储库时会更好)。我使用 msysGit 有一段时间了,但后来转向 Mercurial 并且对它非常满意。
如果您是一名 Windows 开发人员,正在寻找基本的断开连接的修订控制,请选择 Hg。我发现 Git 难以理解,而 Hg 很简单并且与 Windows shell 很好地集成在一起。我下载了 Hg 并按照本教程 (hginit.com)进行操作- 十分钟后,我有了一个本地存储库并重新开始我的项目。
我认为关于“Mercurial vs. Git”的最佳描述是:
它们几乎相同。从我的角度来看,最重要的区别(我的意思是,让我选择一个 DVCS 而不是另一个的原因)是这两个程序如何管理分支。
要使用 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 中的许多操作更快,例如切换到另一个提交、比较提交等。特别是如果这些提交距离很远。
AFAIK mercurial 的方法没有任何优势。
没有。他们都做同样的事情,都表现得差不多。您应该选择一个而不是另一个的唯一原因是如果您帮助一个已经使用一个的项目..
选择一个的另一个可能原因是一个应用程序或服务只支持一个系统。例如,我几乎选择学习 git 因为github ..
还有谷歌的比较(虽然有点旧,2008年完成)
如果我正确理解它们(而且我远非专家),它们基本上都有不同的哲学。我第一次使用 mercurial 9 个月。现在我已经使用 git 了 6。
hg 是版本控制软件。它的主要目标是跟踪软件的版本。
git 是一个基于时间的文件系统。它的目标是为文件系统添加另一个维度。大多数都有文件和文件夹,git增加了时间。它作为 VCS 的工作非常棒是其设计的副产品。
在 hg 中,它总是试图维护整个项目的历史。默认情况下,我相信 hg 在推拉时希望所有用户对所有对象进行所有更改。
在 git 中只有一个对象池和这些跟踪文件(分支/头),它们确定哪些对象集代表处于特定状态的文件树。推或拉时,git 只发送您正在推或拉的特定分支所需的对象,这是所有对象的一小部分。
就 git 而言,没有“1 个项目”。你可以在同一个仓库中拥有 50 个项目,而 git 不会在意。每个都可以在同一个 repo 中单独管理,并且可以正常运行。
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 都有一个叫做“分支”的东西,但它们并不是完全一样的东西。当不同的 repos 之间存在冲突时,就会出现 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 分支,我不知道它是什么。
我在某种程度上理解 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 甚至有命令来决定您要将同一文件中的哪些特定行复制到阶段,因此您也可以单独拆分这些提交。你为什么想这么做?因为作为单独的提交,其他人只能提取他们想要的提交,或者如果有问题,他们可以只恢复有问题的提交。
在 versioncontrolblog 上有一个动态比较图表,您可以在其中比较几个不同的版本控制系统。
在与分支机构(尤其是短期分支机构)合作时存在相当大的差异。
这篇比较 Mercurial 和 Git的文章 (BranchingExplained)对此进行了解释。
您的项目中是否有任何基于 Windows 的合作者?
因为如果有的话,Git-for-Windows GUI 看起来很笨拙、困难、不友好。
相比之下,Mercurial-on-Windows 是显而易见的。
bitbucket.org 的 mercurial 和 github 的 git 之间需要注意的一件事是,mercurial 可以拥有任意数量的私有存储库,但 github 必须升级到付费帐户。所以,这就是我选择使用 mercurial 的 bitbucket 的原因。
去年的某个时候,我为自己的使用评估了 git 和 hg,并决定使用 hg。我觉得它看起来像是一个更干净的解决方案,并且当时在更多平台上运行得更好。不过,这主要是一次折腾。
最近,由于 git-svn 和充当 Subversion 客户端的能力,我开始使用 git。这赢得了我的支持,我现在已经完全切换到 git。我认为它的学习曲线略高(特别是如果你需要探索内部),但它确实是一个很棒的系统。我要去阅读约翰现在发布的那两篇比较文章。
我目前正在从 SVN 迁移到 DVCS(同时在博客上讲述我的发现,我的第一个真正的博客工作......),并且我做了一些研究(=谷歌搜索)。据我所知,你可以用这两个包做大部分事情。似乎 git 有一些更多或更好实现的高级功能,我确实觉得与 windows 的集成对于 mercurial 和 TortoiseHg 来说更好一些。我知道还有 Git Cheetah(我都试过了),但是这种善变的解决方案感觉更健壮。
看看它们都是开源的(对吗?)我认为它们都不会缺少重要的功能。如果某件事很重要,人们会要求它,人们会对其进行编码。
我认为对于常见的做法,Git 和 Mercurial 绰绰有余。他们都有使用它们的大项目(Git -> linux 内核,Mercurial -> Mozilla 基金会项目,当然还有其他),所以我认为两者都没有真正缺乏什么。
话虽如此,我对其他人对此的看法很感兴趣,因为它将成为我写博客的重要来源;-)
在InfoQ 的 DVCS 指南中,有一个关于 git、Mercurial 和 Bazaar 的优秀而详尽的比较表和图表。
我意识到这不是答案的一部分,但在这一点上,我还认为 NetBeans 和 Eclipse 等平台的稳定插件的可用性在哪个工具更适合任务方面发挥了作用,或者更确切地说,哪个工具是最适合“你”的。也就是说,除非你真的想用 CLI 方式来做。
Eclipse(以及基于它的所有东西)和 NetBeans 有时都会在远程文件系统(例如 SSH)和文件的外部更新方面出现问题;这也是为什么您希望您选择“无缝”工作的另一个原因。
我现在也在尝试为自己回答这个问题 .. 我已经将候选人归结为 Git 或 Mercurial .. 感谢大家在不信教的情况下就这个话题提供有用的意见。
mercurial 和 git 的另一个有趣的比较:Mercurial vs Git。主要关注内部结构及其对分支过程的影响。
如果您对 Mercurial 和 Git 的性能比较感兴趣,请查看这篇文章。结论是:
Git 和 Mercurial 都取得了不错的成绩,但在速度和存储库大小之间做出了有趣的权衡。Mercurial 的添加和修改速度都很快,同时可以控制存储库的增长。Git 也很快,但在您重新打包之前,它的存储库会随着修改过的文件快速增长——而这些重新打包可能会非常慢。但是打包的存储库比 Mercurial 的要小得多。
mercurial 网站对两个系统的异同有很大的描述,解释了词汇和底层概念的差异。作为一个长期使用 git 的用户,它确实帮助我理解了 Mercurial 的心态。
有些人认为 VCS 系统必须很复杂。他们鼓励在该领域发明术语和概念。他们可能会认为许多关于这个主题的博士会很有趣。其中可能是设计 Git 的人。
Mercurial 的设计理念不同。开发人员不应该太关心 VCS,而应该把时间花在他们的主要功能上:软件工程。Mercurial 允许用户使用并愉快地滥用系统,而不会让他们犯任何不可恢复的错误。
任何专业工具都必须带有设计清晰且直观的 CLI。Mercurial 用户可以通过发出没有任何奇怪选项的简单命令来完成大部分工作。在 Git 双破折号中,疯狂的选项是常态。如果您是 CLI 人员(老实说,任何有自尊的软件工程师都应该如此),Mercurial 具有很大的优势。
举个例子,假设你错误地做了一个提交。您忘记编辑一些文件。要撤消您在 Mercurial 中的操作,您只需键入:
$ hg rollback
然后,您会收到一条消息,表明系统撤消了您的最后一笔交易。
在 Git 中你必须输入:
$ git reset --soft HEAD^
好吧,假设您知道重置是什么。但除此之外,您还必须知道“--soft”和“--hard”重置是什么(任何直观的猜测?)。哦,当然不要忘记最后的 '^' 字符!(现在里奇的名字是……)
Mercurial 与 kdiff3 和 meld 等 3rd 方工具的集成也更好。生成你的补丁合并你的分支,而不用大惊小怪。Mercurial 还包括一个简单的 http 服务器,您可以通过键入激活它
hg serve
并让其他人浏览您的存储库。
底线是,Git 做了 Mercurial 所做的事情,但方式要复杂得多,而且 CLI 也差得多。如果您想将项目的 VCS 转变为科学研究领域,请使用 Git。如果您想在不太关心的情况下完成 VCS 工作并专注于您的实际任务,请使用 Mercurial。