在git status

时间:2016-04-01 23:09:13

标签: 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")

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

$ python update.py
Doing work...
Done
$ git status
On branch my-branch
nothing to commit, working directory clean

但是,我发现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
$

在上面的代码段中:

  1. 我运行update.py,它替换了从其他地方下载的相同副本的foo.txtbar.txtbaz.txt文件。
  2. git diff-files错误地报告根据git diff man page中描述的原始输出格式,在工作树中就地编辑了这三个文件。
  3. git status正确报告没有任何变化。
  4. git diff-files,在git status之后运行,现在报告没有任何变化。
  5. 运行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. 否则,工作树很脏。提交更改。
    4. 我在update_and_commit_if_needed.py看到一个奇怪的失败:我要进入第三步,但是git commit会抱怨nothing to commit, working directory clean。在追踪该错误时,我发现了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
      $
      

      编辑2 :根据评论中的建议,我尝试将默认值中的core.trustctimecore.ignoreStat反转。在这种情况下,这似乎不会改变git的行为。

1 个答案:

答案 0 :(得分:8)

git diff-index实际上并未检查工作树中的文件内容。相反,它使用文件的统计信息并将其与索引进行比较。实际上,diff-index man page notes

  

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

正如笔记所示,可以通过在git update-index --refresh之前运行diff-files来更新索引的统计条目。 man page for update-index elaborates

  

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

     

例如,您需要在执行git read-tree后执行此操作,以将统计索引详细信息与正确的文件相关联。

update-index --refresh之前运行diff-files会删除我描述的症状,解决问题。