哪些管道命令实现与 git add 相同的效果?
Which plumbing commands achieve the same as git add?
我想通过了解进入
时实际发生的情况来更好地理解git-plumbing
git add $DIRECTORY
和
git add $FILE
它是如何工作的?
阅读 progit's git internals section.
可以得到一个大概的概念
- 如果
$DIRECTORY
是一个目录,类似于find $DIRECTORY -type f -exec git add {} \;
,即递归添加$DIRECTORY
中的所有文件。然后,git add $FILENAME
申请每个文件。
- 检查
.gitignore
(及其 "superiors")
- 检查
.gitattributes
,运行 clean
过滤器(如果适用)
git hash-object -w
clean
ed 内容
然后然后,索引以某种方式获取更新,这涉及git mktree。但是那里到底发生了什么?目录树是仅包含添加的文件还是包含先前提交的所有文件?接下来会发生什么?
git add
没有一个等效的管道命令,但最接近的可能是 git update-index
。 ProGit描述正确:
用目录内容列表替换每个目录。结果是由 add
指定的文件列表,对现在已知在目录中 而不是 的文件进行一些特殊情况处理(即,已删除),以及文件具有特殊索引状态(--assume-unchanged
和 --skip-worktree
)。也就是说,这一步也参考了当前索引。
检查未暂存但被忽略(通过 .gitignore
)的文件并将它们从列表中丢弃(带有警告),除非给出 -f
/ --force
.
(旁注:我没有在子目录上测试过,-f
可能不适用于递归扫描拾取的子目录条目,但仅适用于命令中实际给出的名称行。如果是这种情况,步骤 2 必须与步骤 1 结合,这样即使我们要忽略它们,也不会添加名称,即使使用 -f
。)
应用属性(如果有),根据需要制作临时清理的文件副本。
使用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”条目,这就是它们在包含它们的任何树中的显示方式。)
我想通过了解进入
时实际发生的情况来更好地理解git-plumbinggit add $DIRECTORY
和
git add $FILE
它是如何工作的?
阅读 progit's git internals section.
可以得到一个大概的概念- 如果
$DIRECTORY
是一个目录,类似于find $DIRECTORY -type f -exec git add {} \;
,即递归添加$DIRECTORY
中的所有文件。然后,git add $FILENAME
申请每个文件。 - 检查
.gitignore
(及其 "superiors") - 检查
.gitattributes
,运行clean
过滤器(如果适用) git hash-object -w
clean
ed 内容
然后然后,索引以某种方式获取更新,这涉及git mktree。但是那里到底发生了什么?目录树是仅包含添加的文件还是包含先前提交的所有文件?接下来会发生什么?
git add
没有一个等效的管道命令,但最接近的可能是 git update-index
。 ProGit描述正确:
用目录内容列表替换每个目录。结果是由
add
指定的文件列表,对现在已知在目录中 而不是 的文件进行一些特殊情况处理(即,已删除),以及文件具有特殊索引状态(--assume-unchanged
和--skip-worktree
)。也就是说,这一步也参考了当前索引。检查未暂存但被忽略(通过
.gitignore
)的文件并将它们从列表中丢弃(带有警告),除非给出-f
/--force
.(旁注:我没有在子目录上测试过,
-f
可能不适用于递归扫描拾取的子目录条目,但仅适用于命令中实际给出的名称行。如果是这种情况,步骤 2 必须与步骤 1 结合,这样即使我们要忽略它们,也不会添加名称,即使使用-f
。)应用属性(如果有),根据需要制作临时清理的文件副本。
使用
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”条目,这就是它们在包含它们的任何树中的显示方式。)