сбросить на git push - PullRequest
       10

сбросить на git push

14 голосов
/ 03 апреля 2011

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

есть идеи?

Ответы [ 3 ]

24 голосов
/ 04 апреля 2011

Проблема заключается в том, как команды 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 FAQ «Почему я не вижу изменений в удаленном репо после« git push »?» рекомендует post-update script , который делает именно это , Связанный скрипт также намного безопаснее, так как он делает тайник, если индекс или рабочее дерево загрязнено перед выполнением аппаратного сброса.

16 голосов
/ 21 ноября 2012

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

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
0 голосов
/ 04 апреля 2011

Ну, сценарий, вероятно, не запущен. Он не будет работать через тупой http-сервер. Это будет работать через SSH. Я не уверен с умным http сервером.

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

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

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

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

...