жесткий сброс на git push

У меня есть скрипт хука после получения, сидящий в удаленном репо, который я нажимаю, который делает 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, но когда я захожу на сервер, удаленная рабочая копия вообще не обновляется!

любая идея?


person David    schedule 03.04.2011    source источник
comment
Вы действительно должны опубликовать свой хук-скрипт, когда у вас возникнут проблемы с ним.   -  person Chris Johnsen    schedule 04.04.2011
comment
Крис, мой сценарий пост-получения содержит только одну строку. не надо постить.   -  person David    schedule 04.04.2011


Ответы (3)


Проблема заключается в разнице в том, как команды 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
comment
+1 Аааа, это ужасно. Хуже того, раньше я не осознавал, что $PWD и $GIT_DIR несовместимы для разных хуков при запуске в не голом репозитории. (например, в post-commit они установлены на рабочее дерево и .git соответственно.) - person Mark Longair; 09.04.2011
comment
@Mark: Хм, я не особо обращал внимание на «местные» хуки. Похоже, это могут быть только «удаленные» хуки (варианты получения и обновления), которые настраивают эту проблемную среду. Другие хуки в основном нацелены на действия, которым в любом случае требуется рабочее дерево, и они, похоже, запускаются с разумной конфигурацией для команд Git, которым требуется рабочее дерево (что имеет смысл, поскольку такие хуки обычно вызываются из команд, которым нужно рабочее дерево). . - person Chris Johnsen; 09.04.2011
comment
правильно - я только что написал сообщение в блоге, описывающее переменные среды GIT и текущие каталоги для каждого хука здесь: longair.net/blog/2011/04/09/missing-git-hooks-documentation - person Mark Longair; 09.04.2011

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

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
person leo    schedule 21.11.2012
comment
Даже лучше, чем мутировать окружение и доступно в git до того, как вопрос был задан. - person digenishjkl; 29.07.2014

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

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

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

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

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

person sehe    schedule 03.04.2011
comment
Сообщение HEAD is now at … может исходить только от git checkout или git reset. Ни один из них не является частью обычного push-уведомления, так что скрипт ловушки почти наверняка запускается. - person Chris Johnsen; 04.04.2011
comment
Вы делали какие-либо другие проверки? Особенно проверка HEAD? Читая другой пост, вы должны были получить положительный результат при проверке "GIT_DIR"... - person sehe; 04.04.2011