这里值得一提的是,所有这些方法都使用索引,也就是暂存区,也就是缓存。
当 Git 进行新的提交时,它会使用“索引”中的任何内容。正如短语索引所暗示的,有一个单一的、特殊的、可区分的东西:索引,而不是一个索引。但实际上,Git 可以使用一些 other 索引。我们需要知道什么是“the”索引是,以及作为 the 索引相对于其他索引意味着什么。
简而言之,索引是 Git 用来构建下一次提交的东西。我们从 this 提交中的内容开始,即当前或HEAD 提交。你运行git checkout master 或git checkout branch 或其他什么,Git 用一堆文件填满你的工作树。它将相同的文件放入(单个、特殊、杰出)索引,也称为暂存区。这意味着索引/暂存区开始时充满了许多文件:大多数情况下,工作树中的相同文件,您在其中进行工作。例外情况是某些工作树文件可能未跟踪。
未跟踪文件是不在索引中的文件。就这么简单:索引中not 的任何文件都不会被跟踪;跟踪索引中是的任何文件。索引中的那些开始与您git checkout-ed 的那些相同,git checkout 放入您的工作树中。
然后,您对一堆文件进行大量更改。但是,如果您现在运行git commit,则索引/暂存区域仍然具有原始git checkout 版本,而不是修改后的工作树版本。所以你必须 git add 将更改的文件复制到索引中。
这有点麻烦,所以 Git 有 git add -u 和 git commit -a。但是这两个都只是查看索引中的内容,然后将它们的新工作树版本复制到索引中。所以git commit -a -m "commit message" 不会添加在工作树中但不在在索引中的文件——即当前未跟踪的文件。这与git add -u 相同:只有跟踪的 文件得到更新。
这里有点复杂
除此之外,git commit 可以将路径名作为参数:
git commit -m "some message" file1 file2
例如。但这意味着--only 标志,即仅 提交file1 和file2 中的更改。你也可以运行:
git commit -m "some message" --include file1 file2
这会覆盖--only。
这一切的运作方式是 Git 可以使用 不同的 索引,而不是标准索引。当使用--only 时,Git 所做的是从HEAD 提交构建一个新的临时索引。然后,Git 将工作树中的指定文件复制到这个临时索引中,替换旧版本或添加新文件。然后 Git 从这个临时索引进行提交:新提交与 HEAD 提交具有所有相同的文件,除了由于 --only file1 file2 而添加的任何文件。
当您使用--include 时,Git 通过复制当前索引而不是再次提取HEAD 来创建其临时索引。所以现在无论你有什么git add-ed 都在临时索引中。然后 Git 添加指定的文件,并进行新的提交。
在所有情况下,在 Git 进行新的提交之后,它也必须修复 real 索引,因为现在您已经提交了最新的 file1 和 file2(可能还有其他更新)如果你使用--include)。如果你使用--include,临时索引就变成了真正的索引。
如果你使用--only,这是最复杂的情况。在这里,Git 也将添加的文件复制到实际索引中,但除此之外,单独保留实际索引。这样,您之前上演的任何内容仍然是上演的。新提交中包含 HEAD 提交中的任何内容(通过临时索引),但指定的文件(被 git add 编辑到临时索引中)除外。而且,您刚才特别提交的任何内容现在也将 git add-ed 到 real 索引中,就像您在这些文件上运行 git add 一样。