哪些管道命令实现与 git add 相同的效果?

Which plumbing commands achieve the same as git add?

我想通过了解进入

时实际发生的情况来更好地理解
git add $DIRECTORY

git add $FILE

它是如何工作的?

阅读 progit's git internals section.

可以得到一个大概的概念

然后然后,索引以某种方式获取更新,这涉及git mktree。但是那里到底发生了什么?目录树是仅包含添加的文件还是包含先前提交的所有文件?接下来会发生什么?

git add 没有一个等效的管道命令,但最接近的可能是 git update-index。 ProGit描述正确:

  1. 用目录内容列表替换每个目录。结果是由 add 指定的文件列表,对现在已知在目录中 而不是 的文件进行一些特殊情况处理(即,已删除),以及文件具有特殊索引状态(--assume-unchanged--skip-worktree)。也就是说,这一步也参考了当前索引。

  2. 检查未暂存但被忽略(通过 .gitignore)的文件并将它们从列表中丢弃(带有警告),除非给出 -f / --force .

    (旁注:我没有在子目录上测试过,-f 可能不适用于递归扫描拾取的子目录条目,但仅适用于命令中实际给出的名称行。如果是这种情况,步骤 2 必须与步骤 1 结合,这样即使我们要忽略它们,也不会添加名称,即使使用 -f。)

  3. 应用属性(如果有),根据需要制作临时清理的文件副本。

  4. 使用git update-index --add --remove --replace将修改后的文件写入存储库,更新其索引条目,包括模式更新。 (对于在步骤 3 中清理的文件,您必须按照您的建议使用单独的 git hash-object -w,并使用 --index-info 而不是 --add --remove --replace。)

git mktree 命令根本不会进入此过程,因为索引本身只是一个使用记录不完整的格式(或更准确地说,是几种格式之一;参见 --index-version).

索引允许每个文件名最多四个条目,称为 阶段:阶段 0 是正常的缓存条目,阶段 1 到 3 用于冲突合并。有几个用于标记文件已删除的特殊位,或 --assume-unchanged--skip-worktree--intent-to-add 和一些特殊的内部使用标志,并且 - 尽管 Git 没有 store directories——有目录的索引条目(让Git查看目录的ctime字段,然后让Git快速跳过未修改的目录,前提是它可以信任 OS 维护它)。

git mktree 命令仅在将索引转换为一系列树对象时起作用。 Git 必须为索引中的每个子目录制作一棵树,再加上一棵代表整个索引的顶级树。 (子项目,如果存在的话,已经在索引中作为“gitlink”条目,这就是它们在包含它们的任何树中的显示方式。)