Автоматический деплой из Git? Нет ничего проще!

Cделаем из Git быструю и удобную замену FTP, rsync или чем раньше было принято пользоваться для выгрузки исходников на целевой сервер.

В чём соль?

Огромный плюс такого подхода: вам не нужны никакие дополнительные действия на сервере кроме настройки хуков Git, которые вызываются при git push. Забудьте о мутных шелл-скриптах, которые невозможно сходу понять. Забудьте повышении прав для скриптов через sudo как о страшном сне. Забудьте о безпарольных ssh-ключах для доступа к GitHub и о других неприятных компромиссах. Всё это не нужно. Лишь бы на сервере был Git.

Приступим

На целевом сервере нам нужен репозитарий. Можно пустой.

~/www$ git init
Initialized empty Git repository in /home/example.com/www/.git/

В нём разрешим перезапись текущей ветки.

git config receive.denyCurrentBranch ignore

Добавим хук для сохранения локальных правок.

tee .git/hooks/pre-receive <<EOF
#!/bin/sh
cd ..
GIT_DIR='.git'
env -u GIT_QUARANTINE_PATH git stash save --quiet
git stash show || true
EOF

И хук для развертывания самого последнего коммита в текущей ветке.

tee .git/hooks/post-receive <<EOF
#!/bin/sh
cd ..
GIT_DIR='.git'
git reset --hard
git stash pop --quiet || git reset --hard
EOF

Без бита исполнения Git попросту проигнорирует эти файлы, потому установим его.

chmod +x .git/hooks/pre-receive .git/hooks/post-receive

Теперь расскажем локальному репозитарию об удаленном.

git remote add --track master origin example.com@server.example.net:www

Загрузим основную ветку на целевой сервер.

git push --set-upstream origin master

При первом пуше Git может ругаться на отсутствие HEAD, это нормально.

Что дальше

Дальнейшая работа происходит обычным образом.

git pull
git add -p
git commit
...
git push

Последняя команда выгрузит основную ветку на сервер когда нам это будет нужно.

Аналогично это можно сделать для любой другой ветки заменив master на ее имя в командах. Репозиторий можно использовать как и любой другой для коллективной разработки.

Стоит отметить этот метод бережно относится к внесенным прямо на сервере изменениям (лучше без них!), сохраняя их и накатывая обратно после развертывания ветки. В случае конфликтов вам нужно будет вручную сделать git stash pop на сервере и разрешить конфликты.

Что еще?

В конце хука post-receive можно делать всё, что вам потребно делать при деплое. Например, вызвать make в котором или перезапускать Passenger, или явно сбрасывать кеш в PHP-FPM (при apc.stat = 0), или компилировать файлы LESS, или перезапускать демоны на PHP под контролем Supervisor.