После tar/untar git repo gitk показывает "Локальные незафиксированные изменения, не зарегистрированные в индексе"

У меня есть каталог, содержащий небольшой репозиторий git.

git status, и gitk --all, не показывают незафиксированных изменений.

Если я tar/ сжимаю этот каталог с:

tar czf git-repo.tar.gz git-repo/

Затем перенесите этот tar-файл в тестовый каталог и распакуйте его:

tar xzf git-repo.tar.gz

Когда я

cd test/git-repo/ gitk --all

gitk показывает строку вверху всех коммитов (с обычной красной точкой):

"Локальные незафиксированные изменения, не зарегистрированные в индексе"

git status все еще показывает:

On branch master nothing to commit, working tree clean

Тестирование на различия с:

diff -r git-repo/ test/git-repo/

Не показывает различий.

Если я запустил git clean, эта строка исчезнет.

я пробовал git clean -i в надежде увидеть оскорбительное имя файла, однако оно завершается без запроса интерактивного подтверждения очистки. И после этого Гитк не показывает незафиксированных изменений.

Я работаю: GIT версии 2.11.0

Просто немного сложно объяснить клиенту "Почему происходят незавершенные изменения?" когда на самом деле нет.

Спасибо за понимание...

2 ответа

Решение

gitk просматривает информацию кеша в индексе, чтобы определить, является ли ваш рабочий каталог грязным или нет. Индекс хранит информацию о состоянии текущего рабочего каталога, так что ему не нужно анализировать файлы.

Когда ты бежишь git status, он будет сравнивать содержимое HEAD к содержанию индекса, чтобы показать поэтапные изменения. Это просто и быстро; если идентификатор файла отличается, то его содержимое должно быть другим. Тем не менее, существует более дорогостоящее вычисление, чтобы определить, есть ли в файле изменения без изменений. Файл должен иметь свой SHA1, вычисленный, а затем сравнить со значением в индексе.

Чтобы избежать этого дорогостоящего вычисления, git кэширует struct stat информация о рабочем каталоге содержимого в индексе:

README.md
  ctime: 1516120578:638662531
  mtime: 1516120578:638662531
  dev: 16777220 ino: 1752439
  uid: 501      gid: 20
  size: 13224   flags: 0

Теперь, когда вы бежите git status, это может просто stat содержимое рабочего каталога. Если какой-либо файл имеет одинаковый размер, inode, ctime, mtime и т. Д., То git предполагает, что файл не изменился. Это позволяет git status оставаться в курсе, когда у вас есть неизмененные файлы. Но если какой-либо файл имеет другое значение, он будет хэшировать файл. Если файл имеет тот же хеш (т.е. вы просто запустите touch на файл без изменения содержимого), то индекс будет обновляться с новой информацией кеша. Если вы действительно изменили файл, то git status сообщит о неустановленном изменении.

gitk однако не пытается хэшировать файл, чтобы определить, действительно ли он изменился. Вы можете сами убедиться в этом на тривиальном примере. Здесь у меня есть хранилище с одним файлом, fooбез изменений.

введите описание изображения здесь

Если в командной строке я коснусь файла, обновляя его метку времени:

% touch foo

Теперь gitk сообщает о моем хранилище как о незафиксированных изменениях:

введите описание изображения здесь

Тем не менее, если я бегу git status снова в командной строке обновит информацию о кеше в индексе, а теперь gitk поймет, что на самом деле нет никаких неустановленных изменений:

введите описание изображения здесь

Когда вы копируете свой репозиторий - с рабочим каталогом - вы помещаете на диск рабочий каталог, который не соответствует информации кэша в индексе. git будет фактически перефразировать содержимое, чтобы определить, что ваш рабочий каталог на самом деле не грязный, но gitk не.

Как правило, не очень хорошая идея копировать git-репозиторий и рабочий каталог; Вообще говоря, вы должны проверить новый рабочий каталог.

Хотя ответ Эдварда объясняет проблему, я хочу предложить потенциальный обходной путь.

имеет полезный--argscmdфлаг, который запускается при каждом обновлении. Предполагая, что это не займет слишком много времени (примечание:git gcможет ускорить его), вы можете запуститьgit statusпри каждом обновлении, запустив его так:

      gitk --argscmd="git status >/dev/null"

Это должно скрыть проблему доgitkреализует проверку состояния файла, которая больше соответствует git.

Другие вопросы по тегам