Mercurial 基本上是“没有索引的 git”,因此证明它是可以做到的。任何“为什么”的问题都属于很多灰色地带。但这就是索引提供的内容:
非常快的“git commit”:索引已经包含下一个提交;它只需要重新格式化为树对象和最终提交对象。
一个暂存区,这样你就可以使提交与工作目录不匹配。(不是每个人都认为这是一件好事。)在 Mercurial 中,要提交文件A
并C
同时省略 的工作版本B
,您必须发出提交命令,其中包含(或排除)所有文件的名称一次全部拼写出来。在 git 中,您可以设置一个阶段,运行git diff --cached
(或--staged
),决定它是否正确或需要调整,git add
或者git reset
调整阶段,运行另一个git diff --cached
,等等。(在 Mercurial 中,我发现通过将所有“不需要的”更改移出存储库区域hg commit
,然后将这些更改移回,最容易实现相同的目标。)
易于修改未发布的提交。习惯了 git 中的暂存区和修改过程后,当我在 Mercurial 中进行修改时,我惊讶地发现我当前的整个工作树都变成了新的修改提交。(我不应该感到惊讶,但我是!这又回到了不同的哲学:在 hg 中,你将“尚未准备好”的部分完全移出 repo,以免它们潜入。)
棘手的黑客。(同样,不是每个人都认为这是一件好事。)特别是您可以在索引中设置位,例如“假设不变”或“打算添加”,这会影响未来的提交(再次因为索引在某种意义上是“正在构建的下一个提交”)。
一种在发生合并冲突时保留并因此轻松访问正在合并的文件的方法。
最后一个值得一些额外的解释。假设您正在合并old-fix
到一个文件feature
并在其中重命名。合并意识到它需要从 branch和from获取文件(以其旧名称)并将它们合并。但是存在合并冲突,您的版本系统停止并需要您的帮助来完成合并。feature
FA
old-fix
FA
feature
现在假设您要查看FA
in的版本old-fix
,并将其与FA
in进行比较feature
。如果您从字面上签出分支old-fix
,则没有名为的文件FA
!但是 git 将它存储在索引中,以便您可以看到它,而不必知道旧名称是什么,因为索引正在构建下一个提交(保留新FA
名称)。
您也可以查看feature
版本,当然这更容易,因为您知道它的名称为FA
. 但它在索引中。此外,如gitrevisionsold-fix
中所述,通用(基本)版本(也与 中的旧名称相同)在索引中:
A colon, optionally followed by a stage number (0 to 3) and a
colon, followed by a path, names a blob object in the index at the
given path. A missing stage number (and the colon that follows it)
names a stage 0 entry. During a merge, stage 1 is the common
ancestor, stage 2 is the target branch's version (typically the
current branch), and stage 3 is the version from the branch which
is being merged.
也就是说,:1:FA
是文件的共同祖先FA
,:2:FA
是feature
的版本,:3:FA
是old-fix
的版本。
所有这些精细控制都会导致初学者(有时甚至是专家)出现一些错误,因此 Mercurial 的无索引版本可能更适合您的工作。但是,使用git commit -a
,您将获得与 Mercurial 基本相同的行为,因此您通常可以忽略它,直到您需要它为止。