Проблема заключается в разнице в том, как команды Git ведут себя в среде, созданной для скриптов ловушек, по сравнению с вашей обычной средой.
Во-первых, скрипты ловушек запускаются с их текущим рабочим каталогом, установленным на сам каталог Git (то есть каталог .git/
не голого репозитория). Во-вторых, скрипты ловушек запускаются с установленной переменной окружения GIT_DIR, указывающей на репозиторий Git (опять же, каталог .git/
не голого репозитория).
Обычно, если вы пытаетесь запустить git reset --hard
из каталога .git/
, он завершается со следующим сообщением:
fatal: This operation must be run in a work tree
Но когда установлен GIT_DIR, команды Git предполагают, что текущий каталог является рабочим деревом. Поскольку текущим каталогом при запуске хука является каталог .git/
, ваш git reset --hard
на самом деле «извлекает» ваши файлы рабочего дерева непосредственно в .git/
, а не в его родительский каталог (т. е. теперь у вас есть копия вашего версионированного контента в вашем каталоге .git/
).
Надеемся, что ни один из версионированных материалов в вашем репозитории не имеет пути, совпадающего с пути, которые Git использует в самих репозиториях Git. Если они совпадают, то ваш git reset --hard
перезапишет часть внутренней структуры вашего репозитория, и вы, вероятно, захотите повторно клонировать его из какого-то другого репозитория. Если вы уверены, что ни один из версий контента не конфликтует с внутренними путями Git, вы можете очистить его с помощью этого:
# make a backup of your repository first!
(cd .git && GIT_DIR=$PWD git ls-files -cz | xargs -0 rm)
Это удалит только текущие отслеживаемые файлы (оставятся файлы, которые с тех пор были удалены, но когда-то отслеживались в подсказках, отправленных, когда сломанный хук был активен).
Одним из решений является изменение текущего рабочего каталога на обычное рабочее дерево и удаление GIT_DIR и GIT_WORK_TREE перед вызовом команд Git.
⋮
test "${PWD%/.git}" != "$PWD" && cd ..
unset GIT_DIR GIT_WORK_TREE
# you can now safely use Git commands
⋮
Другое решение — явно сбросить GIT_DIR, установить там GIT_WORK_TREE и chdir. Часто задаваемые вопросы по Git "Почему я не вижу изменений в удаленное репо после «git push»?» рекомендует post-update< /em> сценарий, который делает именно это. Связанный скрипт также намного безопаснее, поскольку он создает тайник, если индекс или рабочее дерево загрязнены, прежде чем выполнять полный сброс.
person
Chris Johnsen
schedule
04.04.2011