![]() |
1
445
免责声明: 我使用git,在git邮件列表中跟踪git的开发,甚至为git(主要是gitweb)做了一些贡献。我从文档中了解到mercurial,还有一些是从freenode上的revctrl irc频道讨论中了解到的。 感谢Mercurial IRC频道上的所有人,他们为本文提供了有关Mercurial的帮助。 总结这里最好有一些表的语法,比如phpmarkdown/multimarkdown/maruku-extension-of-markdown
有一些东西与Git的Mercurial不同,但是还有其他一些东西使它们相似。两个项目都互相借鉴。例如
存储库结构,存储修订在Git中,对象数据库中有四种类型的对象: 斑点 包含文件内容、层次结构的对象 树 存储目录结构的对象,包括文件名和文件权限的相关部分(文件的可执行权限,作为符号链接)。 犯罪 对象,其中包含作者信息、指向由提交(通过项目顶部目录的树对象)表示的修订时存储库状态快照的指针,以及对零个或多个父提交的引用,以及 标签 引用其他对象并可以使用pgp/gpg签名的对象。 Git使用两种存储对象的方法: 释放 格式,其中每个对象存储在单独的文件中(这些文件只写一次,从不修改),以及 拥挤的 在一个文件中存储多个对象的增量压缩格式。操作的原子性是由这样一个事实提供的:对新对象的引用是在写入对象之后写入的(原子性地,使用create+rename技巧)。
Git存储库需要使用
mercurial(据我所知)将文件的历史存储在 文件记录 (我认为,与其他元数据(如重命名跟踪)和一些助手信息一起使用);它使用的平面结构称为 显示 存储目录结构和调用的结构 长乐阁 它存储有关变更集(修订)的信息,包括提交消息和零、一个或两个父级。 汞的用途 交易日记帐 提供操作的原子性,并依赖于 截断 操作失败或中断后要清理的文件。revlogs仅追加。 从Git和Mercurial中的存储库结构可以看出,Git更像对象数据库(或内容寻址文件系统),而Mercurial更像传统的固定字段关系数据库。
差异:
因为Mercurial的固定记录结构 长乐阁 结构,mercurial中的提交只能 最多两个家长 ;Git中的提交可以有两个以上的父级(称为“八达通合并”)。虽然(理论上)可以用一系列的双亲合并来替换章鱼合并,但在Mercurial和Git存储库之间转换时,这可能会导致复杂的问题。 据我所知,Mercurial没有 带注释标签 (标记对象)来自Git。注释标签的特殊情况是 签名标签 (带有PGP/GPG签名);可使用 GpgExtension ,该扩展将与Mercurial一起分发。你不能 标记非提交对象 在Mercurial中,就像在Git中一样,但这并不重要,我认为(一些Git存储库使用标记blob来分发用于验证签名标签的公共PGP密钥)。 参考:分支和标记
在Git引用(分支、远程跟踪分支和标记)中,它们驻留在提交的DAG之外(应该如此)。参考文献
标签
在Mercurial中,可以使用
标签
;标记的存储方式与忽略模式类似。这意味着全局可见的标签存储在版本控制中。
Mercurial还支持
本地标签
,存储在
在git中,标记是存储在
Git处理轻量级标记(直接指向提交)和带注释的标记(指向标记对象,其中包含标记消息,可以选择包含pgp签名,而pgp签名又指向提交),稍有不同,例如,默认情况下,在使用“Git describe”描述提交时,它只考虑带注释的标记。
在Mercurial中,Git没有严格的本地标签等价物。然而,Git最佳实践建议设置单独的公共裸机存储库,将准备好的更改推送到其中,并从中克隆和获取其他存储库。这意味着不推送的标记(和分支)对存储库是私有的。另一方面,您也可以使用除
个人意见:
在我看来,标签应该位于修订图的外部,因为它们是修订图的外部(它们是指向修订图的指针)。标记应该是非版本化的,但可以转移。Mercurial选择使用类似于忽略文件的机制,这意味着它要么必须处理
分支机构
在GIT中
本地分支
(分支提示或分支头)是对提交的命名引用,可以在其中生成新的提交。分支还可以表示活动的开发线,即可以从分支提示访问的所有提交。本地分支机构位于
git中的当前分支(即已签出的分支,以及将要进行新提交的分支)是由head refer引用的分支。可以让head直接指向提交,而不是符号引用;这种匿名匿名匿名分支的情况称为 分离头 (“Git Branch”显示您处于“(无分支)”状态。
在Mercurial中有匿名分支(分支头),可以使用书签(通过
bookmark extension
)这样
书签分支
完全是本地的,并且这些名称(直到1.6版)不能使用mercurial进行转换。可以使用rsync或scp复制
因为可以推/拉1.6个书签。这个
BookmarksExtension
页面上有节
Working With Remote Repositories
. 不同的是,在变化莫测的书签名称中
全球的
,而git中“remote”的定义也描述了
分支名称映射
从远程存储库中的名称到本地远程跟踪分支的名称;例如
Mercurial也有 命名分支 ,其中分支名称是 嵌入的 在提交中(在变更集中)。这样的名称是全局的(在获取时传输)。这些分支名称作为变更集\u2019s元数据的一部分永久记录。使用Modern Mercurial,您可以关闭“已命名分支”并停止记录分支名称。在这个机制中,树枝的尖端是动态计算的。 在我看来,Mercurial的“指定分支”应该称为 提交标签 相反,因为这就是他们的本来面目。在某些情况下,“命名分支”可以有多个提示(多个无子提交),也可以由修订图的几个不相交的部分组成。 在Git中没有类似于那些反复无常的“嵌入式分支”;而且Git的哲学是,尽管可以说分支包含一些提交,但并不意味着提交属于某个分支。 请注意,Mercurial文档仍然建议至少对长寿的分支(每个存储库的单个分支工作流)使用单独的克隆(单独的存储库),即 克隆分支 . 推动中的分支默认情况下的mercurial push 所有头 . 如果你想推动一个分支( 单头 )必须指定要推送的分支的提示修订。可以通过分支提示的修订号(本地到存储库)、修订标识符、书签名称(本地到存储库,不传输)或嵌入分支名称(命名分支)来指定分支提示。 据我所知,如果您推送一系列包含提交的修订,用mercurial的说法标记为“已命名分支”,那么您将在推送到的存储库中拥有这个“已命名分支”。这意味着这些嵌入分支的名称(“命名分支”)是 全球的 (关于给定存储库/项目的克隆)。
违约(以
以上所有假设都假设Git没有配置要通过哪些分支进行推送
提取中的分支
注:
这里我使用git术语,其中“fetch”意味着从远程存储库下载更改。
没有
将这些变化与当地工作相结合。这是什么?
如果我理解正确,默认情况下是mercurial fetches
所有头
从远程存储库,但可以指定要通过其获取的分支“
在git中默认(对于“git clone”创建的“origin”远程,以及对于使用“git remote add”创建的远程)
你可以拿来
单支路
在GIT中使用
这些只是一些默认情况下 ReFSPEC Git语法:使用refspec,您可以指定和/或配置要获取的分支以及存储它们的位置。例如,默认的“fetch all branches”大小写由“+refs/heads/*:refs/remotes/origin/*”通配符refspec表示,“fetch single branch”是“refs/heads/<branch>:”的简写。refspecs用于将远程存储库中分支(refs)的名称映射到本地refs名称。但是,您不需要知道(很多)关于refspecs的信息,就可以有效地使用git(主要归功于“git-remote”命令)。 个人意见: 我个人认为mercurial中的“命名分支”(在changeset元数据中嵌入了分支名称)在其全局名称空间中是错误的设计,特别是对于 分布式的 版本控制系统。例如,让我们以Alice和Bob在其存储库中都有“named branch”命名为“for joe”,而这些分支没有共同点为例。然而,在乔的仓库里,这两个分支会被当作一个分支来对待。因此,您不知何故想出了防止分支名称冲突的约定。这与Git无关,在Joe的存储库中,Alice的“for Joe”分支将是“Alice/for Joe”,Bob的分支将是“Bob/for Joe”。也见 Separating branch name from branch identity 在Mercurial wiki上提出的问题。 Mercurial的“书签分支”目前缺少核心分发机制。
差异:
命名修订在Git中,有许多命名修订的方法(如 git rev-parse MangPLE):
还有涉及reflog的修订说明符,这里没有提到。在Git中,每个对象(无论是commit、tag、tree还是blob)都有其sha-1标识符;有一些特殊的语法,例如“next:documentation”或“next:readme”,以在指定的修订版中引用树(目录)或blob(文件内容)。 Mercurial还有许多命名变更集的方法(如 hg MangPLE):
差异
最新版本在git中命名为head,在mercurial中命名为“tip”;在git中没有空版本。Mercurial和Git都可以有许多根(可以有多个无父提交;这通常是以前独立项目加入的结果)。 另请参见: Many different kinds of revision specifiers 关于以利亚博客的文章(纽伦的)。 个人意见: 我认为 修订号 被高估(至少对于分布式开发和/或非线性/分支历史)。首先,对于分布式版本控制系统,它们必须是存储库本地的,或者需要以特殊的方式将某些存储库视为中央编号机构。第二,历史较长的大型项目可以在5位数字范围内进行修订,因此与缩短为6-7个字符的修订标识符相比,它们只提供了轻微的优势,并且意味着严格的排序,而修订只是部分排序(我的意思是,修订n和n+1不需要是父级和子级)。 修订范围
在Git中,修订范围为
拓扑
. 常见
在Mercurial版本中,范围基于
修订号
. 使用指定范围
这是用Mercurial 1.6修正的,它有新的 拓扑修订范围 ,其中“a..b”(或“a::b”)被理解为同时是x的后代和y的祖先的一组变更集。我猜,这相当于git中的“——祖先路径a..b”。
Git也有符号
更名
善变的使用
重命名跟踪
处理文件重命名。这意味着在提交时保存有关文件重命名事实的信息;在Mercurial中,此信息保存在“增强的diff”表单中,格式为
文件记录
(文件revlog)元数据。结果是你必须使用
Git在版本控制系统中是独一无二的,因为它使用 重命名检测 处理文件重命名。这意味着在需要时检测到文件被重命名的事实:进行合并时,或显示diff时(如果请求/配置)。这样做的优点是可以改进重命名检测算法,并且不会在提交时冻结。
Git和Mercurial都需要使用
在Git中
网络协议Mercurial和Git都支持从同一个文件系统上的存储库中获取和推送,其中存储库URL只是到存储库的文件系统路径。两者都支持从 捆绑文件 .
Mercurial支持通过ssh和HTTP协议获取和推送。对于ssh,需要在目标计算机上有一个可访问的shell帐户和一个已安装/可用的hg副本。对于HTTP访问
Git支持两种用于访问远程存储库的协议:
扩展:脚本能力与扩展(插件)Mercurial在 蟒蛇 ,其中一些核心代码是用C编写的以提高性能。它提供了用于编写的API 扩展 (插件)作为添加额外功能的一种方式。有些功能,如“书签分支”或签名修订,在使用Mercurial分发的扩展中提供,需要打开它。 Git在中实现 C , 珀尔 和 外壳脚本 . Git提供许多低级命令( 管道工程 )适合在脚本中使用。引入新特性的通常方法是将其编写为Perl或Shell脚本,并且当用户界面稳定时,为了性能、可移植性和避免出现角情况(此过程称为 内置 ) Git依赖并基于[Repository]格式和[Network]协议构建。这里没有语言绑定(部分或完整) 重新实施 在其他语言中的Git(其中一些是部分重新实现的,并且部分围绕Git命令包装):JGit(Java,EGIT使用,Eclipse Git插件),Grit(Ruby),达利奇(Python),Gitγ(C1)。 DR |
![]() |
2
56
我认为,通过播放这两个视频,您可以感受到这些系统在哪些方面相似或不同:
吉特岛上的莱纳斯·托瓦尔兹(
http://www.youtube.com/watch?v=4XpnKHJAok8
)
它们在设计上非常相似,但在实现上却非常不同。 我用的是mercurial。据我所知,Git的一个主要区别是它跟踪文件的内容,而不是文件本身。Linus说,如果您将一个函数从一个文件移动到另一个文件,Git将告诉您整个移动过程中单个函数的历史记录。 他们还说Git比HTTP慢,但它有自己的网络协议和服务器。 与Mercurial相比,Git作为SVN胖客户机工作得更好。您可以拉压SVN服务器。此功能在Mercurial中仍在开发中 Mercurial和Git都有非常好的网络托管解决方案(BitBucket和GitHub),但Google代码只支持Mercurial。顺便说一下,他们对Mercurial和Git进行了非常详细的比较,决定支持哪一个。( http://code.google.com/p/support/wiki/DVCSAnalysis )它有很多好的信息。 |
![]() |
3
30
不久前,我写了一篇关于Mercurial分支模型的博客,其中包括了与Git分支模型的比较。也许你会发现它很有趣: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/ |
![]() |
4
25
我经常使用这两种。主要的功能差异在于Git和Mercurial名称在存储库中的分支方式。使用mercurial,分支名称将被克隆并与其变更集一起提取。在Mercurial中添加对新分支的更改并将其推送到另一个存储库时,分支名称将同时被推送。因此,分支名称在Mercurial中或多或少是全局的,并且您必须使用书签扩展名,使其仅具有本地的轻量级名称(如果需要,Mercurial默认使用匿名轻量级代码行,在其术语中称为“heads”)。在Git中,分支名称及其到远程分支的内射映射存储在本地,您必须显式地管理它们,这意味着知道如何做到这一点。这正是Git比Mercurial更难学习和使用的原因。 正如其他人在这里所指出的,有很多微小的差异。分支的区别是很大的。 |
![]() |
5
19
看一看
Git vs. Mercurial: Please Relax
帕特里克·汤姆森的博客,他写道:
请注意,这篇博文是从2008年8月7日开始的,自那以后,这两个配置管理系统都有了很大的改进。 |
![]() |
6
11
Mercurial几乎完全用Python编写。Git的核心是用C语言(应该比Mercurial更快)编写的,工具是用sh、perl、tcl编写的,并且使用标准的gnu-utils。因此,它需要将所有这些实用程序和解释程序带到不包含它们的系统(如Windows)中。 这两种支持都与SVN一起工作,尽管Afaik SVN支持在Windows上为Git中断(可能我只是不走运/跛脚,谁知道呢)。还有一些扩展允许Git和Mercurial之间进行互操作。 Mercurial有很好的 Visual Studio integration . 上次我检查的时候, plugin for Git 正在工作,但速度非常慢。 它们的基本命令集非常相似(init、clone、add、status、commit、push、pull等)。所以,基本的工作流程是相同的。另外,两者都有类似于Tortoissesvn的客户端。
Mercurial的扩展可以用python编写(毫不奇怪!)对于git,它们可以以任何可执行形式(可执行二进制文件、shell脚本等)写入。有些扩展非常强大,比如
|
![]() |
7
11
如果您需要良好的Windows支持,您可能更喜欢Mercurial。 TortoiseHg (Windows资源管理器插件)设法为相当复杂的工具提供一个简单易用的图形界面。作为州政府,您还将拥有 Visual Studio plugin . 但是,上一次我尝试时,SVN接口在Windows上没有那么好地工作。 如果你不介意命令行界面,我推荐Git。不是出于技术原因,而是出于战略原因。Git采用率为 许多的 较高的。看看有多少著名的开源项目从cvs/svn切换到mercurial,有多少项目切换到git。查看与Mercurial托管相比,使用Git支持可以找到多少代码/项目托管提供商。 |
![]() |
8
11
在阅读了所有关于mercurial的文章之后(我仍然相信,毕竟互联网社区是这样认为的),当我开始使用git和mercurial时,我觉得git在命令行工作时更容易适应(我开始使用mercurial和tortoisehg)。
主要是因为git命令是根据我来适当命名的,并且数量较少。
mercurial对执行不同任务的每个命令都有不同的命名,而git命令可以根据情况进行多用途(例如,
Git在内部保存每个已提交文件版本的记录,而hg只保存占地面积更小的变更集。与hg相比,git更容易改变历史,但它又是一个恨它或爱它的特性。我喜欢前者的Hg,后者的Git。 我在hg中错过的是git的子模块特性。hg有子epos,但这不完全是git子模块。 围绕这两者的生态系统也会影响人们的选择:Git必须更受欢迎(但这是微不足道的),Git必须 GitHub 而Mercurial BitBucket ,Mercurial有TortoiseHg,我还没有看到一个和Git一样好的版本。 每一个都有其优点和缺点,其中任何一个你都不会输。 |
![]() |
9
8
退房 Scott Chacon's post 不久以前。 我认为Git有“更复杂”的名声,尽管根据我的经验,它并不比需要的复杂。IMO,Git模型是 方式 更容易理解(标记包含提交(以及指向零个或多个父提交的指针)包含树包含blob和其他树…完成)。 不仅仅是我的经验,Git比Mercurial更令人困惑。我建议你再读一遍 this blog post from Scott Chacon 关于这件事。 |
![]() |
10
5
在我现在的工作中,我使用Git一年多了,在此之前,我在以前的工作中使用Mercurial一年多了。我将从用户的角度提供一个评估。 首先,两者都是分布式版本控制系统。分布式版本控制系统需要改变传统版本控制系统的思维方式,但一旦人们理解它们,实际上在许多方面工作得更好。因此,我认为Git和Mercurial比Subversion、Performance等都要优越得多,分布式版本控制系统和传统版本控制系统之间的差异要比Git和Mercurial之间的差异大得多。 然而,Git和Mercurial之间也存在显著的差异,这使得它们更适合自己的用例子集。 反复无常更容易学习。使用Mercurial几个星期后,我几乎不需要参考文档或注释;即使使用了一年,我仍然需要定期与Git一起参考注释。Git要复杂得多。 这在一定程度上是因为汞只是简单的清洁剂。您很少需要在mercurial中手动进行分支;mercurial将在需要时自动为您创建匿名分支。Mercurial术语更直观;您不必像处理git那样担心“fetch”和“pull”之间的区别。Mercurial的车少了一点。有一些文件名区分大小写的问题,在使用Git和Mercurial跨平台推送项目时,常常会引起问题;这在Mercurial中已经修复了一段时间,而上次我检查的Git中还没有修复。你可以告诉mercurial有关文件重命名的信息;对于git,如果它不能自动检测到重命名——这在我的经验中是一个非常成功或失败的建议——那么就根本无法跟踪重命名。 然而,Git额外复杂的另一个原因是,它中的大部分都需要支持额外的特性和功能。是的,在Git中处理分支更加复杂——但是另一方面,一旦你有了分支,用那些在Mercurial中几乎不可能实现的分支做事情就不难了。重新平衡分支是其中之一:您可以移动分支,使其基础(而不是分支时的主干状态)现在是主干的状态;当有许多人在同一代码基础上工作时,这大大简化了版本历史,因为每个对主干的推送都可以显示为连续的,而不是而不是交织在一起。类似地,将分支上的多个提交折叠为单个提交要容易得多,这同样有助于保持版本控制历史的整洁:理想情况下,对一个特性的所有工作都可以在主干中显示为单个提交,替换开发人员在开发该特性时可能进行的所有次要提交和子分支。 最后,我认为在Mercurial和Git之间的选择应该取决于您的版本控制项目有多大,以同时处理这些项目的人数来衡量。例如,如果您有一组十几个或更多的人在一个单块Web应用程序上工作,那么Git更强大的分支管理工具将使它更适合您的项目。另一方面,如果您的团队正在开发一个异构的分布式系统,并且在任何时候只有一两个开发人员在处理任何一个组件,那么为每个组件项目使用一个mercurial存储库将使开发更加顺利地进行,同时减少存储库管理开销。 底线:如果您有一个大型团队开发单个大型应用程序,请使用Git;如果您的单个应用程序很小,任何规模都来自于此类应用程序的数量而不是大小,请使用Mercurial。 |
![]() |
11
4
一个与dvcss本身完全无关的区别是: Git似乎很受C开发人员的欢迎。Git实际上是Linux内核的存储库,这可能是它如此受C开发人员欢迎的原因。对于那些只在Linux/Unix环境中工作的人来说,这一点尤其如此。 Java开发人员似乎更青睐Git。可能有两个原因:一个是许多非常大的Java项目托管在MySimple上,包括JDK本身。另一个是对JavaCAMP的人的结构和干净文档的吸引,而这些人发现Git不一致的WRT命令命名和缺少文档。我不是说这是真的,我是说人们已经习惯了他们通常的栖息地的东西,然后他们倾向于从中选择DVC。 我想,python开发人员几乎完全喜欢mercurial。事实上,除了Mercurial是基于Python之外,没有其他合理的理由。(我也使用了mercurial,我真的不明白为什么人们会对dvc的实现语言大惊小怪。我一个字也不懂python,如果不是因为它列在某个基于python的地方,我就不会知道了)。 我认为你不能说一个DVC比另一个更适合一种语言,所以你不应该从中选择。但事实上,人们选择(部分)是基于他们作为社区的一部分最容易接触到的DVC。 (不,我没有使用统计数据来支持我上面的声明。)这都是基于我自己的主观性) |