一段时间以来,我一直在我的个人项目中使用subversion。

我听到越来越多关于Git、Mercurial和DVCS的好消息。

我想尝试一下DVCS,但我对这两种选择都不太熟悉。

Mercurial和Git之间有什么区别?

注意:我并不是要找出哪一个是“最好的”,或者我应该从哪一个开始。我主要寻找它们相似和不同的关键领域,因为我想知道它们在实现和理念方面有何不同。


当前回答

如果您需要良好的Windows支持,您可能更喜欢Mercurial。TortoiseHg (Windows资源管理器插件)设法为一个相当复杂的工具提供了一个简单易用的图形界面。在这里,你还会有一个Visual Studio插件。但是,上次我尝试时,SVN界面在Windows上工作得不太好。

如果您不介意使用命令行界面,我推荐使用Git。不是出于技术原因,而是出于战略原因。git的采用率高得多。看看有多少著名的开源项目正在从cvs/svn切换到Mercurial,又有多少项目正在切换到Git。看看与Mercurial托管相比,你能找到多少支持git的代码/项目托管提供商。

其他回答

看看Scott Chacon不久前的帖子。

我认为git以“更复杂”而闻名,尽管在我的经验中,它并没有比它需要的更复杂。在我看来,git模型更容易理解(标签包含提交(以及指向零个或多个父提交的指针)包含树,包含blob和其他树…完成)。

git并不比mercurial更令人困惑,这不仅仅是我的经验。我建议你再读一遍Scott Chacon关于这个问题的博文。

与DVCSs本身完全无关的一个区别是:

Git似乎很受C开发人员的欢迎。Git是Linux内核的事实上的存储库,这可能是它在C开发人员中如此受欢迎的原因。对于那些只在Linux/Unix世界中工作的人来说尤其如此。

Java developers seem to favor Mercurial over Git. There are possibly two reasons for that: One is that a number of very large Java projects are hosted on Mercurial, including the JDK itself. Another is that the structure and clean documentation of Mercurial appeals to people coming from the Java camp whereas such people find Git inconsistent wrt command naming and lacking in documentation. I'm not saying that is actually true, I'm saying people have got used to something from their usual habitat and then they tend to choose DVCS from that.

我认为Python开发人员几乎都喜欢Mercurial。除了Mercurial是基于Python的这一事实之外,实际上没有任何合理的原因。(我也使用Mercurial,我真的不明白为什么人们对DVCS的实现语言大惊小怪。我不懂Python的一个字,如果不是因为它在某个地方列出了它是基于Python的,那么我不会知道)。

我认为你不能说一个DVCS比另一个更适合一种语言,所以你不应该从中做出选择。但在现实中,人们选择(部分)是基于他们在社区中接触最多的DVCS。

(不,我没有使用统计数据来支持我上面的说法..这都是基于我自己的主观)

I use both quite regularly. The major functional difference is in the way Git and Mercurial name branches within repositories. With Mercurial, branch names are cloned and pulled along with their changesets. When you add changes to a new branch in Mercurial and push to another repository, the branch name is pushed at the same time. So, branch names are more-or-less global in Mercurial, and you have to use the Bookmark extension to have local-only lightweight names (if you want them; Mercurial, by default, uses anonymous lightweight codelines, which in its terminology are called "heads"). In Git, branch names and their injective mapping to remote branches are stored locally and you must manage them explicitly, which means knowing how to do that. This is pretty much where Git gets its reputation for being harder to learn and use than Mercurial.

正如其他人在这里注意到的,有很多很多微小的差异。分支是一个很大的微分器。

After reading all over that Mercurial is easier (which I still believe it is, after all the internet community is of the opinion), when I started working with Git and Mercurial I felt Git is relatively simpler for me to adapt to (I started off with Mercurial with TortoiseHg) when working from the command line, mainly because the git commands were named appropriately according to me and are fewer in number. Mercurial has different naming for each command that does a distinct job, while Git commands can be multipurpose according to situation (for eg, checkout). While Git was harder back then, now the difference is hardly substantial. YMMV.. With a good GUI client like TortoiseHg, true it was much easier to work with Mercurial and I did not have to remember the slightly confusing commands. I'm not going into detail how every command for the same action varied, but here are two comprehensive lists: 1 from Mercurial's own site and 2nd from wikivs.

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           Git               ║                Mercurial                                                                       ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull                    ║ hg pull -u                                                                                     ║
║ git fetch                   ║ hg pull                                                                                        ║
║ git reset --hard            ║ hg up -C                                                                                       ║
║ git revert <commit>         ║ hg backout <cset>                                                                              ║
║ git add <new_file>          ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.)                            ║
║ git add <file>              ║ Not necessary in Mercurial.                                                                    ║
║ git add -i                  ║ hg record                                                                                      ║
║ git commit -a               ║ hg commit                                                                                      ║
║ git commit --amend          ║ hg commit --amend                                                                              ║
║ git blame                   ║ hg blame or hg annotate                                                                        ║
║ git blame -C                ║ (closest equivalent): hg grep --all                                                            ║
║ git bisect                  ║ hg bisect                                                                                      ║
║ git rebase --interactive    ║ hg histedit <base cset> (Requires the HisteditExtension.)                                      ║
║ git stash                   ║ hg shelve (Requires the ShelveExtension or the AtticExtension.)                                ║
║ git merge                   ║ hg merge                                                                                       ║
║ git cherry-pick <commit>    ║ hg graft <cset>                                                                                ║
║ git rebase <upstream>       ║ hg rebase -d <cset> (Requires the RebaseExtension.)                                            ║
║ git format-patch <commits>  ║ hg email -r <csets> (Requires the PatchbombExtension.)                                         ║
║   and git send-mail         ║                                                                                                ║
║ git am <mbox>               ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)  ║
║ git checkout HEAD           ║ hg update                                                                                      ║
║ git log -n                  ║ hg log --limit n                                                                               ║
║ git push                    ║ hg push                                                                                        ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝

Git在内部保存提交文件的每个版本的记录,而Hg只保存更改集,占用空间更小。与Hg相比,Git更容易改变历史,但它又是一个令人讨厌或喜欢的特性。前者我喜欢Hg,后者我喜欢Git。

我在Hg中错过的是Git的子模块特性。Hg有subrepos,但那不是Git的子模块。

围绕这两者的生态系统也会影响一个人的选择:Git必须更受欢迎(但这无关紧要),Git有GitHub,而Mercurial有BitBucket, Mercurial有TortoiseHg,我还没有看到与Git一样好的同类产品。

每一种都有它的优点和缺点,用它们中的任何一种你都不会输。

如果您需要良好的Windows支持,您可能更喜欢Mercurial。TortoiseHg (Windows资源管理器插件)设法为一个相当复杂的工具提供了一个简单易用的图形界面。在这里,你还会有一个Visual Studio插件。但是,上次我尝试时,SVN界面在Windows上工作得不太好。

如果您不介意使用命令行界面,我推荐使用Git。不是出于技术原因,而是出于战略原因。git的采用率高得多。看看有多少著名的开源项目正在从cvs/svn切换到Mercurial,又有多少项目正在切换到Git。看看与Mercurial托管相比,你能找到多少支持git的代码/项目托管提供商。