为什么执行`git status`会改变后续`git diff-index`的结果?

Wil*_*ell 4 git docker

考虑:

$ git --version
git version 2.20.1 (Apple Git-117)
$ git diff-index --quiet HEAD ; echo $?
1
$ git status > /dev/null
$ git diff-index --quiet HEAD ; echo $?
0
Run Code Online (Sandbox Code Playgroud)

这是在具有不区分大小写文件系统的 macos 上。(我不知道这是否相关。)在发生这种情况的主机上,有一个运行 debian 的 docker 镜像并挂载了相同的目录,而在 docker 镜像中,发生了相反的行为:

$ git diff-index --quiet HEAD ; echo $?
0
# At this point, `git status` was invoked outside the docker image
$ git --version
git version 2.20.1
$ git diff-index --quiet HEAD ; echo $?
1
Run Code Online (Sandbox Code Playgroud)

需要说明的是,这里执行的命令顺序是:git diff-index在docker镜像上(返回0),git diff-index在主机上(返回1),git status在主机上,git diff-index在主机上(返回0),git diff-index在docker镜像上(返回1)。

基本上,如果我git-status在一个环境中运行,git diff-index将在该环境中成功(返回 0)而在另一个环境中失败。关于发生了什么的任何想法?这没什么大不了的,我怀疑文件系统不区分大小写是罪魁祸首,但我希望有一个可靠的解释。

Gil*_*il' 6

我遇到了类似的问题,git diff-files我认为原因是一样的。这不需要涉及 Docker 或不区分大小写的文件系统,尽管这些可能会加剧问题。

Git 维护有关文件内容的信息缓存。通常,这是透明的,高级命令如git statusgit diff根据需要更新缓存。

诸如git diff-index和 之类的低级命令git diff-files旨在返回快速但近似的结果。他们不更新缓存。如果他们确定他们比较的东西是相同的,他们就会返回 0,但是当他们返回 1 时,这意味着“我不知道这些东西是相同的”。如果缓存条目已过时,则这些内容可能相同但git diff-xxx不知道。

我不知道缓存是如何工作的。在您的第一个实验中,似乎第一次调用git diff-index注意到缓存条目已过时,因此返回 1 表示“我不知道”。然后git status更新缓存,第二次调用git diff-index查看有效的缓存条目并能够得出结论,文件是相同的。在您的第二个实验中,git status在 Docker 容器外运行似乎创建git diff-index了容器内被认为是陈旧的缓存条目,因此第二次调用git diff-index返回 1 表示“我不知道”。

我的解决方案是忘记低级命令并坚持使用git diff --quiet.