如果我对它们的理解正确(而且我远不是这方面的专家),它们基本上都有不同的哲学。我第一次使用 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 中使用相当大的 chromium 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 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 甚至有命令来决定您要将同一文件中的哪些特定行复制到阶段,这样您也可以单独拆分这些提交。你为什么想这么做?因为作为单独的提交,其他人只能提取他们想要的提交,或者如果有问题,他们可以只恢复有问题的提交。