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获取文件(以其旧名称)并将它们合并。但是存在合并冲突,您的版本系统停止并需要您的帮助来完成合并。featureFAold-fixFAfeature
现在假设您要查看FAin的版本old-fix,并将其与FAin进行比较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 基本相同的行为,因此您通常可以忽略它,直到您需要它为止。