Reset hard on git push

У меня есть крюк post-receive script, сидящий на удаленном репо, я нажимаю на то, что делает git reset --hard

Что-то вроде этого:

$ git push opal
Counting objects: 74, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (45/45), done.
Writing objects: 100% (53/53), 16.68 KiB, done.
Total 53 (delta 20), reused 0 (delta 0)
remote: warning: updating the current branch
remote: HEAD is now at 88f1e35 tweak lavalamp styles

То, что я не понимаю здесь, - удаленный говорит, что голова теперь находится в XXX, но когда я вхожу на сервер - удаленная рабочая копия вообще не обновляется!

любая идея?

Ответ 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.

Ответ 2

Короче говоря, используйте однострочный крючок:

git --git-dir=. --work-tree=$PWD/.. reset --hard

Чтобы быть более точным, отредактируйте файл .git/hooks/post-receive на сервере:

#!/bin/sh
git --git-dir=. --work-tree=$PWD/.. reset --hard

Установите его исполняемый файл:

chmod +x .git/hooks/post-receive

При нажатии на это репо от клиента он должен сказать что-то вроде:

HEAD is now at abcd123 comment

Ответ 3

Ну, script, вероятно, не запускается. Он не будет работать через немой http-сервер. Он пройдет через ssh. Я не уверен с умным http-сервером.

Если это не так, вы должны проверить разрешающую способность "выполнить" на крюке (chmod + x.git/hooks/post-receive). Пока вы на нем, обычно проверяйте owenership и разрешения.

Если это выглядит нормально, просто включите logstatement в первую строку в script (например, date "%T $0 executed" >> /tmp/debug_hook.log) и проверьте файл журнала, чтобы узнать, обновлено ли что-либо.

Кроме того, возможно, что толчок фактически ничего не делает (все обновлено). В этом случае имеет смысл, что крючок не называется

Если все это не дает подсказки, отправьте .git/config, поскольку он находится на сервере (или, по крайней мере, частично). Получает ли git log -1 HEAD ожидаемый результат на сервере? Ваш крюк script содержит все, что может переопределить GIT_DIR, GIT_WORK_TREE или GIT_INDEX_FILE?