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

在Git中,索引的目的是什么?,git,git-branch,working-directory,git-stash,git-workflow,Git,Git Branch,Working Directory,Git Stash,Git Workflow,我知道典型的Git工作流是一个三步过程:(修改工作树中的文件)->(使用Git add/rm/etc)修改索引)->(运行Git commit) 然而,为什么Git不把工作树当作临时区域呢?例如,您修改了一个文件,它会自动“暂存”以便提交,除非您明确告诉git不要暂存它。这更像是一种“选择退出”的方法,而不是“选择加入”,这对我来说很有意义,因为您的工作树中99%的文件将被提交。它还将使整个git stash机制变得多余,因为您可以简单地从工作树创建一个临时分支,而不是savea stash t

我知道典型的Git工作流是一个三步过程:(修改工作树中的文件)->(使用
Git add/rm/etc
)修改索引)->(运行
Git commit

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

如果工作树和索引之间的分离有一个合理的原因,我很乐意听到它。。。也许我的困惑源于我还没有完全了解Git这一事实。

该站点实际上对暂存区是什么、它存在的原因、它提供的好处以及在提交时绕过它的方法有一个清晰的认识

摘自

集结区 与其他系统不同,Git有一个称为“暂存区”或“索引”的东西。这是一个中间区域,可以在完成提交之前对提交进行格式化和检查

Git与其他工具不同的一点是,它可以快速暂存一些文件并提交它们,而无需提交工作目录中所有其他修改过的文件,也无需在提交过程中在命令行上列出它们

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

当然,如果您不需要这种控制,Git也可以很容易地忽略此功能—只需在commit命令中添加“-a”,以便将所有文件的所有更改添加到临时区域

希望这有帮助。干杯

Mercurial基本上是“没有索引的git”,因此证明了它是可以实现的。任何“为什么”的问题都会陷入很多灰色地带。但这是该指数所提供的:

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

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

  • 易于修改未发布的提交。习惯了git中的暂存区和修改过程后,当我在Mercurial中进行修改时,我惊讶地发现我当前的整个工作树都变成了新的修改提交。(我本不应该感到惊讶,但我是!这又回到了另一种哲学:在hg中,你将“尚未准备就绪”部分完全移出回购,以免它们溜进。)

  • 狡猾的黑客。(同样,并非所有人都认为这是一件好事。)特别是,您可以在索引中设置位,如“假定未更改”或“打算添加”,这会影响将来的提交(同样是因为从某种意义上说,索引是“正在构建的下一个提交”)

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

最后一个应该得到一些额外的解释。假设您正在将
旧补丁
合并到
功能
,并且在
功能
中,一个文件被重命名为
FA
。合并实现了它需要从分支
old fix
获取文件(使用其旧名称),并从
feature
获取
FA
,然后合并它们。但是存在合并冲突,您的版本系统将停止并需要您的帮助来完成合并

现在假设您想查看
old fix
FA
的版本,将其与
功能中的
FA
进行比较。如果您确实签出分支
旧修复程序
,则没有名为
FA
的文件!但是git将其存储在索引中,这样您就可以看到它,而不必知道旧名称是什么,因为索引正在构造下一个提交(保留新的
FA
名称)

您还可以查看
功能
版本,当然这更容易,因为您知道它的名称为
FA
。但它在索引中。此外,索引中还包含通用(基本)版本(与
旧补丁
中的旧名称相同),如中所述:

也就是说,
:1:FA
是文件
FA
的共同祖先,
:2:FA
功能
的版本,
:3:FA
旧补丁
的版本

所有这些精细的控制都会给初学者(有时甚至是专家)带来一些错误,因此Mercurial的无索引版本可能更适合您的工作。但是,使用git commit-a
,您可以获得与Mercurial基本相同的行为,因此您可以
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.