哪个管道命令实现与git add相同?

时间:2016-05-09 11:38:54

标签: git 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(及其“上级”)的检查
  • .gitattributes进行检查,运行clean过滤器(如果适用)
  • git hash-object -w clean ed内容

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

1 个答案:

答案 0 :(得分:2)

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

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

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

    (旁注:我没有在子目录上测试过这个问题,并且-f可能不适用于递归扫描所选择的子目录条目,但实际上只能用于名称在命令行中给出。如果是这种情况,则必须将步骤2与步骤1结合起来,以便即使使用{{1}我们也不会忽略它们,也不会添加名称}。)

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

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

  5. --add --remove --replace命令根本不会进入此过程,因为索引本身只是一个平面文件,使用的文档格式很差(或者更确切地说,是几种格式之一;请参阅git mktree )。

    索引允许每个文件名最多四个条目,称为阶段:阶段0是普通缓存条目,阶段1到3是冲突合并。删除标记文件有几个特殊位,或--index-version--assume-unchanged--skip-worktree和一些特殊的内部使用标志,即使Git没有存储目录 - 有目录的索引条目(让Git查看目录的--intent-to-add字段,然后让Git快速跳过未修改的目录,前提是它可以信任操作系统来维护它。)

    ctime命令仅在将索引转换为一系列树对象时才起作用。 Git必须为索引中的每个子目录创建一个树,加上一个表示整体索引的顶级树。 (子项目,如果存在,已经在索引中作为" gitlink"条目,这是它们在包含它们的任何树中出现的方式。)