Ответ 1
Проблема заключается в различии в том, как команды Git ведут себя в среде, созданной для скриптов hook в сравнении с вашей обычной средой.
Сначала скрипты hook запускаются с их текущим рабочим каталогом, установленным в самом каталоге Git (т.е. в каталоге .git/
небедного репозитория). Во-вторых, скрипты hook запускаются с набором переменных среды GIT_DIR и указывают на репозиторий Git (опять же, каталог .git/
не-голого репозитория).
Обычно, если вы попытаетесь запустить git reset --hard
из каталога .git/
, он умрет со следующим сообщением:
fatal: This operation must be run in a work tree
Но когда установлен GIT_DIR, команды Git предполагают, что текущий каталог является рабочим деревом. Поскольку текущий каталог при запуске hook является каталогом .git/
, ваш git reset --hard
фактически "проверяет" ваши рабочие файлы дерева непосредственно в .git/
вместо его родительского каталога (т.е. Теперь у вас есть копия вашего версированного содержимого в вашем каталоге .git/
).
Надеемся, что ни один из версий с версиями в вашем репозитории не имеет путей, которые совпадают с именами путей, которые Git использует в Git репозиториях. Если они совпадают, то ваш git reset --hard
перезапишет некоторый бит внутренней структуры вашего репозитория, и вы, вероятно, захотите повторно клонировать его из какого-либо другого репозитория. Если вы уверены, что ни один из версий с версиями не конфликтует с внутренними именами путей Git s, вы можете очистить его следующим образом:
# 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
⋮
Другим решением является явно reset GIT_DIR, установите GIT_WORK_TREE и chdir. Git FAQ "Почему я не вижу изменений в удаленном репо после" git push "?" рекомендует post-update script, который делает именно это. Связанный script также намного безопаснее, так как он делает занос, если индекс или рабочее дерево загрязнены, прежде чем выполнять жесткий reset.