2016-04-01 2 views
3

У меня есть сценарий, update.py, который загружает новые версии файлов отслеживаются в моем хранилище мерзавца:Git изменения Diff-файлы вывода после статуса мерзавца

$ 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.txt, bar.txt и baz.txt файлы с идентичными копиями загруженных из других источников.
  2. git diff-files неправильно сообщает, что эти три файла были отредактированы на месте в дереве работ в соответствии с исходным форматом вывода, описанным на git diff man page.
  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. Run update.py.
  2. Если git diff-files возвращает ноль, рабочее дерево чистое, а update.py ничего не изменило. Выход.
  3. В противном случае рабочее дерево загрязнено. Зафиксируйте изменения.

Я видел странный провал в update_and_commit_if_needed.py: Я хотел бы получить к третьему шагу, но тогда git commit будет жаловаться, что там было nothing to commit, working directory clean. Отслеживая эту ошибку, я обнаружил это странное поведение git diff-files.

Я использую git версию 2.5.0 на OS X 10.11.4 (15E65).


EDIT 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 
$ 

EDIT 2: Как было предложено в комментарии, я попытался переворачивания core.trustctime и core.ignoreStat от их значений по умолчанию. В этом случае это не изменяет поведение git.

+0

Очевидно, что это какая-то ошибка. Точно какой ... ну, эта часть * не * ясна. :-) Поскольку индекс хранит результаты «stat» для целей кеша, ваша ОС может быть релевантной. См. Также настройки 'core.trustctime' и' core.ignoreStat' в 'git config'. – torek

+0

Wow, Man! Вы только что исследовали причины долговременного/недочеты/gitk, которые по существу страдают от этой ошибки: иногда она демонстрирует, что есть изменения, но не может их продемонстрировать, а после «F5» (перезагрузить) флаг изменения исчезает. Я уверен, что быстрая проверка включает в себя какую-то «статистику» без фактического сравнения контента, но это только спекуляции, а не настоящие расследования. – user3159253

ответ

2

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 или привести индекс уточненный для изменения режима/контента. Но он делает это, чтобы «повторно сопоставить» информацию о статусе файла с индексом, чтобы обновить индекс для файла, который не был изменен, но где устаревшая запись устарела.

Например, вы должны сделать это после выполнения git read-tree, чтобы связать данные индекса индекса с соответствующими файлами.

Запуск update-index --refresh до diff-files стирает описанные мной симптомы, решая проблему.

Смежные вопросы