在git status之后git diff-files输出更改

rav*_*ron 10 git git-diff

我有一个脚本,update.py它下载我的git存储库中跟踪的新版本文件:

$ python update.py
Doing work...
Done
$ git status
On branch my-branch
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   foo.txt
    modified:   bar.txt
    modified:   baz.txt

no changes added to commit (use "git add" and/or "git commit -a")
Run Code Online (Sandbox Code Playgroud)

有时,下载的文件与已有的文件相同HEAD,因此下载后工作目录是干净的:

$ python update.py
Doing work...
Done
$ git status
On branch my-branch
nothing to commit, working directory clean
Run Code Online (Sandbox Code Playgroud)

但是,我发现git diff-files在替换文件时似乎感到困惑,即使它们的内容相同:

$ python update.py
Doing work...
Done
$ git diff-files
:100644 100644 ffa91f655007c56f209cf15fee13c55991a76e18 0000000000000000000000000000000000000000 M  foo.txt
:100644 100644 dc05558729c3c94a088aa63da3bbd8f1213b8cf3 0000000000000000000000000000000000000000 M  bar.txt
:100644 100644 002cc3f53dc64b89b1b91adbb6fe61035ba9e832 0000000000000000000000000000000000000000 M  baz.txt
$ git status
On branch my-branch
nothing to commit, working directory clean
$ git diff-files
$
Run Code Online (Sandbox Code Playgroud)

在上面的代码段中:

  1. 我跑update.py,它取代了foo.txt,bar.txtbaz.txt与从其他地方下载相同的复制文件.
  2. git diff-files根据git diff手册页中描述的原始输出格式,错误地报告这三个文件已在工作树中就地编辑.
  3. git status 正确地报告没有任何改变.
  4. git diff-files,运行之后git status,现在报告没有任何变化.

运行后update.py,git diff-files将继续错误地报告更改,直到我运行git status,之后它再次表现.

这里发生了什么?git diff-files当没有报告时,为什么报告会发生变化?


万一你好奇为什么这会给我带来麻烦,这里有更多的背景:

我有另一个脚本,update_and_commit_if_needed.py执行以下操作:

  1. update.py.
  2. 如果git diff-files返回零,则工作树是干净的,并且update.py没有任何改变.出口.
  3. 否则,工作树很脏.提交更改.

我看到一个奇怪的失败update_and_commit_if_needed.py:我会进入第三步,但随后git commit会抱怨有nothing to commit, working directory clean.在追踪那个bug时,我发现了这种奇怪的行为git diff-files.

我在OS X 10.11.4(15E65)上使用git版本2.5.0.


编辑1:我发现了一种简单的方法来重现这种行为:

$ git diff-files
$ git status
On branch my-branch
nothing to commit, working directory clean
$ cp foo.txt ~
$ mv ~/foo.txt .
$ git diff-files
:100755 100755 20084b5d6da359748f62c259c24f2b9cc2359780 0000000000000000000000000000000000000000 M  foo.txt
$ git status
On branch my-branch
nothing to commit, working directory clean
$ git diff-files
$
Run Code Online (Sandbox Code Playgroud)

编辑2:正如评论所说,我已经试过反转core.trustctimecore.ignoreStat从它们的默认值.在这种情况下,这似乎不会改变git的行为.

rav*_*ron 12

git diff-index实际上并没有检查工作树中文件的内容.相反,它使用文件的统计信息并将其与索引进行比较.实际上,该diff-index手册页注释:

与此类型的其他命令一样,git diff-index实际上根本不查看文件的内容.所以也许kernel/sched.c实际上并没有改变,只是你碰到了它.在任何一种情况下,都需要注意git update-index它才能使索引同步.

如注释所示,索引的stat条目可以通过git update-index --refresh之前运行来更新diff-files.详细说明手册页update-index:

--refresh不会计算新的sha1文件或使模式/内容更改的索引保持最新.但它所做的是将文件的统计信息与索引"重新匹配",以便您可以刷新尚未更改但文件条目过期的文件的索引.

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

跑步update-index --refresh之前diff-files擦除我描述的症状,解决问题.