English ▾ 主题 ▾ 最新版本 ▾ git-update-index 上次更新于 2.45.3

名称

git-update-index - 将工作树中的文件内容注册到索引

概要

git update-index
	     [--add] [--remove | --force-remove] [--replace]
	     [--refresh] [-q] [--unmerged] [--ignore-missing]
	     [(--cacheinfo <mode>,<object>,<file>)…​]
	     [--chmod=(+|-)x]
	     [--[no-]assume-unchanged]
	     [--[no-]skip-worktree]
	     [--[no-]ignore-skip-worktree-entries]
	     [--[no-]fsmonitor-valid]
	     [--ignore-submodules]
	     [--[no-]split-index]
	     [--[no-|test-|force-]untracked-cache]
	     [--[no-]fsmonitor]
	     [--really-refresh] [--unresolve] [--again | -g]
	     [--info-only] [--index-info]
	     [-z] [--stdin] [--index-version <n>]
	     [--show-index-version]
	     [--verbose]
	     [--] [<file>…​]

描述

修改索引。提到的每个文件都会更新到索引中,并且任何*未合并*或*需要更新*的状态都会被清除。

另请参见 git-add[1],以了解在索引上执行一些最常见操作的更友好的方式。

git update-index 处理它被告知的文件的方式可以使用各种选项进行修改

选项

--add

如果指定的文件尚未在索引中,则添加该文件。默认行为是忽略新文件。

--remove

如果指定的文件在索引中但缺少,则将其删除。默认行为是忽略已删除的文件。

--refresh

查看当前索引并检查是否需要通过检查 stat() 信息来进行合并或更新。

-q

安静模式。如果 --refresh 发现索引需要更新,则默认行为是报错退出。此选项使 git update-index 继续执行。

--ignore-submodules

不要尝试更新子模块。只有在 --refresh 之前传递此选项才有效。

--unmerged

如果 --refresh 在索引中找到未合并的更改,则默认行为是报错退出。此选项使 git update-index 继续执行。

--ignore-missing

在 --refresh 期间忽略缺失的文件

--cacheinfo <模式>,<对象>,<路径>
--cacheinfo <模式> <对象> <路径>

直接将指定的信息插入索引中。为了向后兼容,你也可以将这三个参数作为三个单独的参数给出,但是建议新用户使用单参数形式。

--index-info

从 stdin 读取索引信息。

--chmod=(+|-)x

设置更新文件的执行权限。

--[no-]assume-unchanged

指定此标志后,不会更新为路径记录的对象名称。相反,此选项设置/取消设置路径的“假设未更改”位。当“假设未更改”位打开时,用户承诺不更改文件,并允许 Git 假设工作树文件与索引中记录的内容匹配。如果要更改工作树文件,则需要取消设置该位以告知 Git。当在具有非常慢的 lstat(2) 系统调用的文件系统(例如 cifs)上处理大型项目时,这有时很有用。

如果 Git 需要修改索引中的此文件,例如在合并提交时,Git 将失败(优雅地);因此,如果假设未跟踪的文件在上游更改,则需要手动处理该情况。

--really-refresh

--refresh 类似,但无条件地检查 stat 信息,而不考虑“假设未更改”设置。

--[no-]skip-worktree

指定其中一个标志后,不会更新为路径记录的对象名称。相反,这些选项设置和取消设置路径的“skip-worktree”位。有关更多信息,请参见下面的“Skip-worktree 位”部分。

--[no-]ignore-skip-worktree-entries

即使指定了 --remove 选项,也不要删除 skip-worktree(又名“仅索引”)条目。

--[no-]fsmonitor-valid

指定其中一个标志后,不会更新为路径记录的对象名称。相反,这些选项设置和取消设置路径的“fsmonitor valid”位。有关更多信息,请参见下面的“文件系统监视器”部分。

-g
--again

在索引条目与 HEAD 提交的条目不同的路径上运行 git update-index 本身。

--unresolve

如果在合并期间意外清除,则恢复文件的*未合并*或*需要更新*状态。

--info-only

不要为跟随此标志的所有 <file> 参数在对象数据库中创建对象;只需将其对象 ID 插入索引中。

--force-remove

即使工作目录中仍然存在此类文件,也要从索引中删除该文件。(暗示 --remove。)

--replace

默认情况下,如果文件 path 存在于索引中,则 git update-index 拒绝添加 path/file 的尝试。类似地,如果文件 path/file 存在,则无法添加文件 path。使用 --replace 标志,与要添加的条目冲突的现有条目将被自动删除,并显示警告消息。

--stdin

不要从命令行获取路径列表,而是从标准输入读取路径列表。默认情况下,路径由 LF 分隔(即每行一个路径)。

--verbose

报告正在从索引中添加和删除的内容。

--index-version <n>

以命名的磁盘格式版本写出生成的索引。支持的版本为 2、3 和 4。当前默认版本为 2 或 3,具体取决于是否使用了额外的功能,例如 git add -N。使用 --verbose,还报告此命令之前和之后索引文件使用的版本。

版本 4 执行简单的路径名压缩,可将大型存储库的索引大小减少 30%-50%,从而加快加载时间。Git 自 2012 年 10 月发布的 1.8.0 版本以来就支持它,并且在 2016 年将其添加到 libgit2,并在 2020 年添加到 JGit。此手册页的较旧版本称其为“相对年轻”,但如今应将其视为成熟的技术。

--show-index-version

报告磁盘索引文件使用的索引格式版本。参见上面的 --index-version

-z

仅对 --stdin--index-info 有意义;路径用 NUL 字符而不是 LF 分隔。

--split-index
--no-split-index

启用或禁用拆分索引模式。如果拆分索引模式已启用,并且再次给出 --split-index,则 $GIT_DIR/index 中的所有更改都将推送回共享索引文件。

无论 core.splitIndex 配置变量的值如何,这些选项都有效(请参见 git-config[1])。但是,当更改与配置的值相悖时,会发出警告,因为配置的值将在下次读取索引时生效,这将消除该选项的预期效果。

--untracked-cache
--no-untracked-cache

启用或禁用未跟踪的缓存功能。请在使用前使用 --test-untracked-cache 启用它。

无论 core.untrackedCache 配置变量的值如何,这些选项都有效(请参见 git-config[1])。但是,当更改与配置的值相悖时,会发出警告,因为配置的值将在下次读取索引时生效,这将消除该选项的预期效果。

--test-untracked-cache

仅对工作目录执行测试,以确保可以使用未跟踪的缓存。如果您确实要使用它,则必须在使用 --untracked-cache--force-untracked-cachecore.untrackedCache 配置变量之后手动启用未跟踪的缓存。如果测试失败,则退出代码为 1,并且一条消息解释了未按需工作的内容,否则退出代码为 0,并且会打印 OK。

--force-untracked-cache

--untracked-cache 相同。提供用于与旧版本的 Git 向后兼容,其中 --untracked-cache 曾经暗示 --test-untracked-cache,但是此选项将无条件地启用扩展。

--fsmonitor
--no-fsmonitor

启用或禁用文件系统监视器功能。无论 core.fsmonitor 配置变量的值如何,这些选项都有效(请参阅 git-config[1])。但是,当更改与配置的值相悖时,会发出警告,因为配置的值将在下次读取索引时生效,这将消除该选项的预期效果。

--

不要将任何其他参数解释为选项。

<文件>

要操作的文件。请注意,以 . 开头的文件会被丢弃。这包括 ./filedir/./file。如果你不希望这样,请使用更简洁的名称。同样适用于以 / 结尾的目录和带有 // 的路径。

使用 --REFRESH

--refresh 不会计算新的 sha1 文件或使索引与模式/内容更改保持同步。但是,它做的是将文件的 stat 信息与索引“重新匹配”,以便你可以刷新索引,即使文件没有被更改,但 stat 条目已经过期。

例如,你可能需要在执行 git read-tree 之后执行此操作,以将 stat 索引详细信息与正确的文件链接起来。

使用 --CACHEINFO 或 --INFO-ONLY

--cacheinfo 用于注册不在当前工作目录中的文件。这对于最小签出合并很有用。

要假装你有一个具有模式和 sha1 的 path 上的文件,例如

$ git update-index --add --cacheinfo <mode>,<sha1>,<path>

--info-only 用于注册文件,而不将它们放置在对象数据库中。这对于仅状态存储库很有用。

--cacheinfo--info-only 的行为类似:索引已更新,但对象数据库未更新。当对象在数据库中但文件在本地不可用时,--cacheinfo 很有用。 当文件可用,但你不想更新对象数据库时,--info-only 很有用。

使用 --INDEX-INFO

--index-info 是一种更强大的机制,允许你从标准输入馈送多个条目定义,并且专门为脚本设计。 它可以接受三种格式的输入

  1. 模式 SP 类型 SP sha1 TAB 路径

    此格式是将 git ls-tree 输出填充到索引中。

  2. 模式 SP sha1 SP 阶段 TAB 路径

    此格式是将更高阶的阶段放入索引文件中,并与 git ls-files --stage 输出匹配。

  3. 模式 SP sha1 TAB 路径

    此格式不再由任何 Git 命令生成,但 update-index --index-info 现在和将来都会支持它。

要将更高阶段的条目放入索引中,应首先通过为该路径馈送 mode=0 的条目来删除该路径; SHA-1 只要格式正确就可以。然后以第三种格式馈送必要的输入行。

例如,从这个索引开始

$ git ls-files -s
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0       frotz

你可以将以下输入馈送到 --index-info

$ git update-index --index-info
0 0000000000000000000000000000000000000000	frotz
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1	frotz
100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2	frotz

输入的第一行将 0 作为模式馈送,以删除该路径; SHA-1 只要格式正确就无关紧要。然后,第二行和第三行馈送该路径的阶段 1 和阶段 2 条目。完成上述操作后,我们将得到以下结果

$ git ls-files -s
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1	frotz
100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2	frotz

使用“假定未更改”位

Git 中的许多操作都依赖于你的文件系统具有高效的 lstat(2) 实现,以便可以廉价地检查工作树文件的 st_mtime 信息,以查看文件内容是否已从索引文件中记录的版本更改。不幸的是,某些文件系统的 lstat(2) 效率低下。如果你的文件系统是其中之一,你可以将“假定未更改”位设置为你未更改的路径,以使 Git 不进行此检查。请注意,在路径上设置此位并不意味着 Git 将检查文件的内容以查看它是否已更改,它会使 Git 省略任何检查并假定它更改。当你更改工作树文件时,你必须通过删除“假定未更改”位来显式地告知 Git,无论是在修改之前还是之后。

为了设置“假定未更改”位,请使用 --assume-unchanged 选项。要取消设置,请使用 --no-assume-unchanged。要查看哪些文件设置了“假定未更改”位,请使用 git ls-files -v(请参阅 git-ls-files[1])。

该命令会查看 core.ignorestat 配置变量。当此值为 true 时,使用 git update-index paths... 更新的路径以及使用其他 Git 命令更新索引和工作树(例如 git apply --index, git checkout-index -ugit read-tree -u)的路径会自动标记为“假定未更改”。请注意,如果 git update-index --refresh 发现工作树文件与索引匹配,则不会设置“假定未更改”位(如果你想将它们标记为“假定未更改”,请使用 git update-index --really-refresh)。

有时,用户会将假定未更改位与 skip-worktree 位混淆。有关差异的解释,请参见下面的“Skip-worktree 位”部分中的最后一节。

示例

仅更新和刷新已检出的文件

$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
在设置了 core.ignorestat 的效率低下的文件系统上
$ git update-index --really-refresh              (1)
$ git update-index --no-assume-unchanged foo.c   (2)
$ git diff --name-only                           (3)
$ edit foo.c
$ git diff --name-only                           (4)
M foo.c
$ git update-index foo.c                         (5)
$ git diff --name-only                           (6)
$ edit foo.c
$ git diff --name-only                           (7)
$ git update-index --no-assume-unchanged foo.c   (8)
$ git diff --name-only                           (9)
M foo.c
  1. 强制 lstat(2) 为与索引匹配的路径设置“假定未更改”位。

  2. 标记要编辑的路径。

  3. 这会执行 lstat(2) 并发现索引与路径匹配。

  4. 这会执行 lstat(2) 并发现索引与路径匹配。

  5. 将新版本注册到索引会设置“假定未更改”位。

  6. 并假定它未更改。

  7. 即使在你编辑它之后。

  8. 你可以在事后告知更改。

  9. 现在它使用 lstat(2) 进行检查,发现它已更改。

SKIP-WORKTREE 位

可以在一个(很长的)句子中定义 Skip-worktree 位:告诉 git 在合理的情况下避免将文件写入工作目录,并在文件不存在于工作目录中时将该文件视为未更改。

请注意,并非所有 git 命令都会注意此位,有些命令仅部分支持它。

与 skip-worktree 位相关的 update-index 标志和 read-tree 功能早于 git-sparse-checkout[1] 命令的引入,后者提供了一种更简单的方式来配置和处理 skip-worktree 位。如果你想减少你的工作树以仅处理存储库中的一部分文件,我们强烈建议使用 git-sparse-checkout[1],而不是低级别的 update-index 和 read-tree 原语。

skip-worktree 位的主要目的是启用稀疏检出,即拥有仅存在一部分路径的工作目录。设置 skip-worktree 位后,Git 命令(例如 switchpullmerge)将避免写入这些文件。但是,这些命令有时会在重要情况下写入这些文件,例如在合并或变基期间发生冲突。Git 命令还将避免将缺少此类文件视为有意删除; 例如,git add -u 不会为这些文件暂存删除,并且 git commit -a 也不会创建删除这些文件的提交。

尽管此位看起来类似于假定未更改位,但其目标不同。 假定未更改位用于将文件留在工作树中,但让 Git 省略检查其更改并假定该文件未更改(尽管如果它可以确定无需 stat 该文件就可以确定该文件已更改,则可以自由地记录更改)。 skip-worktree 告诉 Git 忽略缺少该文件的情况,避免在通常更新大部分工作目录的命令(例如 checkoutswitchpull 等)尽可能地更新该文件,并且不要让它的缺席记录在提交中。请注意,在稀疏检出中(由 git sparse-checkout 设置或通过将 core.sparseCheckout 配置为 true),如果在索引中将文件标记为 skip-worktree 但在工作树中找到了该文件,则 Git 将清除该文件的 skip-worktree 位。

拆分索引

此模式专为具有非常大索引的存储库而设计,旨在减少重复写入这些索引所花费的时间。

在此模式下,索引分为两个文件,$GIT_DIR/index 和 $GIT_DIR/sharedindex.<SHA-1>。更改累积在 $GIT_DIR/index(拆分索引)中,而共享索引文件包含所有索引条目并保持不变。

当拆分索引中的条目数达到 splitIndex.maxPercentChange 配置变量指定的级别时,拆分索引中的所有更改都会推回到共享索引文件(请参阅 git-config[1])。

每次创建新的共享索引文件时,如果旧的共享索引文件的修改时间早于 splitIndex.sharedIndexExpire 配置变量指定的时间,则会删除这些文件(请参阅 git-config[1])。

为了避免删除仍在使用的共享索引文件,每次基于共享索引文件创建或从中读取新的拆分索引时,其修改时间都会更新为当前时间。

未跟踪缓存

此缓存旨在加速涉及确定未跟踪文件的命令,例如 git status

此功能的工作方式是记录工作树目录的 mtime,然后省略读取目录以及对那些 mtime 未更改的目录中的文件执行 stat 调用。 为此,如果目录中的文件被添加、修改或删除,则底层操作系统和文件系统必须更改目录的 st_mtime 字段。

你可以使用 --test-untracked-cache 选项测试文件系统是否支持该功能。 在旧版本的 Git 中,--untracked-cache 选项用于隐式执行该测试,但现在不再是这种情况。

如果你想启用(或禁用)此功能,则使用 core.untrackedCache 配置变量(请参阅 git-config[1])比使用 --untracked-cache 选项来为每个存储库执行 git update-index 更容易,特别是如果你想在你使用的所有存储库中都这样做,因为你可以仅在你的 $HOME/.gitconfig 中将配置变量设置为 true (或 false)一次,然后让它影响你接触的所有存储库。

core.untrackedCache 配置变量更改时,下次命令读取索引时,未跟踪缓存将被添加到索引或从索引中删除。而当使用 --[no-|force-]untracked-cache 时,未跟踪缓存会被立即添加到索引或从索引中删除。

在 2.17 之前,未跟踪缓存存在一个错误,其中用指向另一个目录的符号链接替换目录可能会导致错误地显示 git 跟踪的文件为未跟踪文件。 请参阅 git.git 的“状态:添加一个显示 core.untrackedCache 错误的失败测试”提交。 一种解决方法是(并且这可能适用于未来未发现的其他错误)

$ git -c core.untrackedCache=false status

还表明,在用文件替换目录的非符号链接情况下,此错误也会影响未跟踪缓存的内部结构,但尚未报告任何导致错误的“git status”输出的情况。

在某些情况下,git 2.17 之前的版本编写的现有索引将引用不再存在的目录,这可能会导致在“git status”上打印许多“无法打开目录”警告。 这些是针对先前被默默丢弃的现有问题的新警告。

与上述错误一样,解决方案是一次性使用 core.untrackedCache=false 运行“git status”,以清除剩余的错误数据。

文件系统监视器

此功能旨在加速具有大型工作目录的存储库的 git 操作。

它使 Git 能够与文件系统监视器协同工作(参见 git-fsmonitor--daemon[1] 以及 githooks[5] 的 "fsmonitor-watchman" 部分),后者可以告知 Git 哪些文件已被修改。这使 Git 能够避免必须使用 lstat() 来查找每个被修改的文件。

当与未跟踪缓存结合使用时,它可以通过避免扫描整个工作目录以查找新文件的成本来进一步提高性能。

如果您想要启用(或禁用)此功能,使用 core.fsmonitor 配置变量(参见 git-config[1])比在每个仓库中使用 --fsmonitor 选项来 git update-index 更容易,特别是如果您想在您使用的所有仓库中都这样做,因为您可以只在您的 $HOME/.gitconfig 中设置一次配置变量,使其影响您所接触的所有仓库。

core.fsmonitor 配置变量更改时,下次命令读取索引时,文件系统监视器会被添加到索引或从索引中删除。当使用 --[no-]fsmonitor 时,文件系统监视器会立即添加到索引或从索引中删除。

配置

该命令遵循 core.filemode 配置变量。如果您的仓库位于可执行位不可靠的文件系统上,则应将其设置为 *false*(参见 git-config[1])。这会导致该命令忽略索引中记录的文件模式与文件系统上的文件模式之间的差异,如果它们仅在可执行位上有所不同。在这种不幸的文件系统上,您可能需要使用 *git update-index --chmod=*。

类似地,如果 core.symlinks 配置变量设置为 *false*(参见 git-config[1]),则符号链接将作为普通文件检出,并且此命令不会将记录的文件模式从符号链接修改为常规文件。

该命令会查看 core.ignorestat 配置变量。请参阅上面的 *使用 "assume unchanged" 位* 部分。

该命令还会查看 core.trustctime 配置变量。当 inode 更改时间经常被 Git 之外的某些东西修改时(文件系统爬虫和备份系统使用 ctime 来标记已处理的文件),这可能很有用(参见 git-config[1])。

可以通过 core.untrackedCache 配置变量启用未跟踪缓存扩展(参见 git-config[1])。

注意

用户经常尝试使用 assume-unchanged 和 skip-worktree 位来告诉 Git 忽略对已跟踪文件的更改。但这不会按预期工作,因为 Git 在执行某些操作时仍然可能会根据索引检查工作树文件。一般来说,Git 不提供忽略对已跟踪文件的更改的方法,因此建议使用替代解决方案。

例如,如果您想要更改的文件是某种配置文件,则存储库可以包含一个示例配置文件,然后可以将其复制到被忽略的名称并进行修改。存储库甚至可以包含一个脚本,将示例文件视为模板,自动修改和复制它。

GIT

属于 git[1] 套件的一部分

scroll-to-top