хук после получения не работает - есть ли шанс понять, почему?

Я реализую этот подход для отправки обновлений на мой веб-сайт:

создал голый репозиторий для отправки

$ mkdir website.git && cd website.git
$ git init --bare

И добавил следующий хук:

$ mkdir /var/www/example.com
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/example.com git checkout -f
$ chmod +x hooks/post-receive

когда я нажимаю на веб-сайт.git из локального репозитория, обновление работает нормально. Но никакие файлы не добавляются в /var/www/example.com. Как я могу выяснить, что здесь может быть не так? Какой-то журнал или что-то в этом роде?

РЕДАКТИРОВАТЬ ----------------------

Проблема устранена, если я нажму на ветку master на repoRemote, а не на demo. Почему так?


person Max Koretskyi    schedule 12.11.2013    source источник


Ответы (6)


Изменить, декабрь 2016 г .: люди все еще находят этот старый ответ, и теперь, спустя 3 года, я действительно понимаю, в чем настоящая проблема. Проблема возникает, когда вы используете перехватчик после получения для развертывания нескольких разных веток. Если вы развернете только одну ветку из пустого репозитория, у вас будет меньше проблем. Git продолжает развиваться, и «лучшее» решение для автоматического развертывания нескольких веток может различаться в зависимости от того, какая у вас версия Git. См. также Развертывание Git после получения перестает работать в случайных точках.

(Исходный ответ ниже строки.)


Я обнаружил, что git checkout -f всегда нужно имя ветки; разрешение использовать HEAD в голых репозиториях не очень предсказуемо.

Вы также можете столкнуться с проблемами с индексом (git напишет его в чистом репо, но иногда он путается). Лучше всего git checkout -f deployment-branch в новый, свежий, пустой каталог. (Должно работать, чтобы установить индексный файл для каждой ветки развертывания, я просто никогда не экспериментировал с этим.)

Если ваш голый репозиторий будет довольно активен в других ветвях, а не в тех, которые используются для развертывания, рекомендуется обернуть код более причудливым сценарием оболочки, который проверяет, действительно ли была изменена рассматриваемая ветвь развертывания. То есть, если кто-то обновит web-devel, нет смысла повторно повторно развертывать deployment-branch, который на этот раз не обновлялся.

person torek    schedule 12.11.2013
comment
Спасибо, я отредактировал свой вопрос с найденным решением. Но я не понимаю, почему это так. Может быть, это объясняет это git checkout -f always needs a branch name? В чистом репо нельзя создать ветку demo, и существует только ветка master? - person Max Koretskyi; 12.11.2013
comment
Если вы в своем личном репозитории запускаете git checkout без имени ветки, что он проверяет и почему? (Это в качестве упражнения: вы должны выяснить, откуда checkout знает, что извлекать.) Какую ветку вы ожидаете, что git выгружает в /var/www/example.com, и как вы ожидаете, что он узнает, какую ветку извлекать? - person torek; 12.11.2013
comment
Вы сообщаете ему, что нужно проверить, указав имя ветки. Если я не укажу его, то команда вырождается, чтобы проверить текущую ветку, что является прославленным отсутствием операций с довольно дорогими побочными эффектами. Текущая ветвь — это то, на что указывает HEAD. В моем случае это ветвь master, я думаю. Теперь я вижу, что вы указываете и почему это происходит. ОК, но при этом - git checkout -f demo выдает эту ошибку git branch fatal: This operation must be run in a work tree даже если демо-ветка существует git branch показывает demo, но HEAD не указывает на нее. - person Max Koretskyi; 13.11.2013
comment
Точнее, он использует HEAD, который в голом репозитории... ну: обычно HEAD обновляется, чтобы соответствовать вашему рабочему каталогу, когда вы работаете, но на самом деле вы не работаете в голом репо! В любом случае, в голом репо есть HEAD, просто потому, что git всегда должен иметь его [если вы удалите его и запустите команду git, git скажет, что я не могу найти здесь каталог git], но это редко то, что вы хотите, чтобы это было . В любом случае, git checkout -f demo должно работать, если установлено GIT_WORK_TREE или если вы используете аргумент --work-tree=. - person torek; 13.11.2013
comment
Большое спасибо! git checkout -f deployment-branch сработало, как вы сказали, в первый раз это не удалось, так как у меня был неверный путь к GIT_WORK_TREE, поэтому, вероятно, он не знал, где находится рабочее дерево. - person Max Koretskyi; 13.11.2013

В Git 2.13 (второй квартал 2017 г.) выявлена ​​и исправлена ​​еще одна возможная причина проблем с перехватом после получения: если для GIT_WORK_TREE задан неверный путь.

См. зафиксировать ce83ead, commit aac3eaa (8 марта 2017 г.), автор Йоханнес Шинделин (dscho).
(Объединено Юнио С. Хамано -- gitster -- в commit ba37c92, 13 марта 2017 г.)

Пример (который вылетит только с Git 2.12)

GIT_WORK_TREE=/.invalid/work/tree &&
export GIT_WORK_TREE &&
git rev-parse
# dies with error code 128

Ошибка была появилась в Git 2.12.

person VonC    schedule 14.03.2017

Из приведенных выше комментариев о надежности таргетинга на определенные ветки - я нашел этот смысл, который нацелен на основную ветку из хука после получения.

#!/bin/bash 
set -eu

TARGET="/deployment-location-here"
GIT_DIR="/trigger-location-here"
BRANCH="master"

while read oldrev newrev ref
do
        # only checking out the master (or whatever branch you would like to deploy)
        if [[ $ref = refs/heads/"$BRANCH" ]];
        then
                echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
                git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f
        else
                echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
        fi
done
person johndpope    schedule 13.11.2019

Я делаю это на своих сайтах:

#!/bin/sh
unset $(git rev-parse --local-env-vars)
cd /var/www/example.com
git pull
person JBarberU    schedule 12.11.2013

cd .git/hooks
mv post-receive post-receive-inner

теперь создайте новый post-receive:

#!/bin/bash
set -x
./post-receive-inner "$@" 1>/tmp/git.log 2>&1 

Сделайте этот исполняемый файл и повторите попытку, результаты должны оказаться в /tmp/git.log

person Oliver Matthews    schedule 12.11.2013
comment
Я создал новую папку hooks/post-receive-inner и переместил в нее хук post-receive. Это то, что мне нужно было сделать? Поскольку в журнале в настоящее время указано следующее: hooks/post-receive: line3: ./post-receive-inner: No such file or directory - person Max Koretskyi; 12.11.2013
comment
это то, что я сделал в первый раз :). То же сообщение. Не могли бы вы указать команды Linux, которые мне нужно выполнить, чтобы устранить мою возможную ошибку? - person Max Koretskyi; 12.11.2013
comment
./post-receive-inner потерпит неудачу, потому что . — это пустой каталог репо, а не каталог hooks/. ./hooks/post-receive-inner будет работать. (Но параметр -x не будет перенесен; для отладочной трассировки вам может понадобиться sh -x hooks/post-receive-inner.) - person torek; 12.11.2013

Сделайте скрипт исполняемым:

chmod +x .git/hooks/post-receive
person Claudio    schedule 12.11.2013
comment
Он сделал chmod в командах, показанных выше (это репозиторий --bare, поэтому файл называется hooks/post-receive без части .git/). - person torek; 12.11.2013