我有一个脚本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
$
在上面的代码段中:
foo.txt
,bar.txt
和baz.txt
文件。git diff-files
错误地报告根据git diff man page中描述的原始输出格式,在工作树中就地编辑了这三个文件。git status
正确报告没有任何变化。git diff-files
,在git status
之后运行,现在也报告没有任何变化。运行update.py
后,git diff-files
将继续错误地报告更改,直到我运行git status
,此后它会再次显示。
这里发生了什么?为什么git diff-files
报告时没有变化?
如果你很好奇为什么这会给我带来麻烦,这里有更多的背景信息:
我有另一个脚本,update_and_commit_if_needed.py
执行以下操作:
update.py
。git diff-files
返回零,则工作树是干净的,update.py
没有改变任何内容。退出。我在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.trustctime
和core.ignoreStat
反转。在这种情况下,这似乎不会改变git的行为。
答案 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
会删除我描述的症状,解决问题。