在Git中,索引的目的是什么?

时间:2014-11-20 01:13:17

标签: git git-branch working-directory git-stash git-workflow

据我所知,典型的Git工作流程分为三个步骤:(修改工作树中的文件) - > (使用git add/rm/etc修改索引) - > (运行git commit)。

但是,为什么Git不将工作树视为临时区域?例如,你修改一个文件,它会自动“暂存”进行提交,除非你特意告诉git不要暂存它。这更像是一种“选择退出”的方法,而不是“选择加入”,这对我来说很有意义,因为工作树中99%的文件都将被提交。它还会使整个git stash机制变得多余,因为您可以简单地从工作树创建一个临时分支,而不是save以后隐藏apply

如果工作树和索引之间存在分离的正当理由,我很乐意听到它...也许我的困惑源于我还没有完全理解Git的事实

2 个答案:

答案 0 :(得分:4)

Git网站实际上有一个good explanation的暂存区域,它存在的原因,它提供的好处,以及在提交时绕过它的方法。

取自http://git-scm.com/about/staging-area

  

临时区域

     

与其他系统不同,Git有一种称为“临时区域”或“索引”的东西。这是一个中间区域,可以在完成提交之前格式化和审查提交。

     

将Git与其他工具区分开来的一件事是,可以快速暂存一些文件并提交它们,而无需在工作目录中提交所有其他修改过的文件,或者在提交期间必须在命令行上列出它们

     

这允许您仅暂存已修改文件的某些部分。在您意识到忘记提交其中一个之前,对文件进行两个逻辑上无关的修改的日子已经一去不复返了。现在,您可以暂停当前提交所需的更改,并为下一次提交暂存另一个更改。此功能可根据需要扩展到文件的多个不同更改。

     

当然,如果您不想进行这种控制,Git也可以轻松忽略此功能 - 只需在您的提交命令中添加'-a',以便将所有文件的所有更改添加到暂存区域

希望这会有所帮助。干杯!

答案 1 :(得分:2)

Mercurial基本上是“没有索引的git”,因此证明可以完成。任何“为什么”的问题都属于很多灰色地带。但这就是索引提供的内容:

  • 非常快“git commit”:索引已包含下一个提交;它只需要重新格式化为树对象和最终提交对象。

  • 暂存区域,以便您可以使提交与工作目录不匹配。 (并非所有人都认为这是一件好事。)在Mercurial中,要在省略A的工作版本的同时提交文件CB,您必须发出一个名为所有要包含(或排除)的文件一次拼写出来。在git中,您可以设置一个阶段,运行git diff --cached(或--staged),确定是否正确或需要调整,git addgit reset来调整阶段,运行另一个git diff --cached,等等。 (在Mercurial中,我发现通过将所有“不需要的”更改移出存储库区域hg commit,最简单的方法来实现同样的目的,然后将这些更改移回。)

  • 易于修改未发布的提交。习惯于在git中使用暂存区域和修改进程,当我在Mercurial中进行修改时,我惊讶地发现我的整个当前工作树成为新修改的提交。 (我不应该感到惊讶,但我是这样!再次回到不同的哲学:在hg中,你完全将“尚未准备好”的部分从回购中移出,以免它们潜入。)

    < / LI>
  • 棘手的黑客攻击。 (同样,不是每个人都认为这是一件好事。)特别是你可以在索引中设置比特,如“假设未改变”或“意图添加”,这会影响未来的提交(再次因为索引在某种意义上说,“正在构建的下一个提交“)。

  • 当发生合并冲突时,一种保持并因此轻松访问正在合并的文件的方法。

最后一个值得一些额外的解释。假设您要将old-fix合并到feature,而在feature中,文件已重命名为FA。合并意识到它需要从分支old-fix获取文件(在其旧名称下),并从FA获取feature,并合并它们。但是存在合并冲突,您的版本系统会停止并需要您完成合并的帮助。

现在假设您要查看FAold-fix的版本,并将其与FA中的feature进行比较。如果您真的检查分支old-fix,则没有名为FA的文件!但是git将它存储在索引中,以便您可以看到它,而不必知道旧名称是什么,因为索引正在构建 next 提交(保留新的FA名称)。

您还可以查看feature版本,但当然这更容易,因为您知道它的名称为FA。但它在索引中存在。此外,公共(基础)版本(也与old-fix中的旧名称相同)位于索引中,如gitrevisions中所述:

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:FAfeature的版本,:3:FAold-fix的版本。

所有这些精细控制都会给初学者(有时甚至是专家)带来一些错误,因此Mercurial的无索引版本可能更适合您的工作。但是,使用git commit -a,您获得与Mercurial基本相同的行为,因此您可以经常忽略它直到您需要它。