Развертывание проекта с помощью Git push

Можно ли развернуть веб-сайт с помощью git push? У меня есть подозрение, что это как-то связано с использованием git хуки для выполнения git reset --hard на стороне сервера, но как мне это сделать?

Я предполагаю, что это применимо только в ситуациях, когда есть только один производственный сервер, верно?

Rijk 13.03.2012 20:24

@Rijk Что ж, вы можете отправлять запросы на несколько серверов одновременно с помощью Git, но как только вы дойдете до этого уровня, вам может понадобиться реальное решение, а не такой взлом.

Kyle Cronin 13.03.2012 20:32

Мне удалось успешно использовать капистрано в моих проектах, который, хотя изначально был разработан для развертывания приложений Ruby on Rails, хорошо работает с PHP и другими проектами.

user1559306 28.07.2012 11:56

Перевел ответы на русский язык на ру.со: ru.stackoverflow.com/questions/428483/…

Nick Volynkin 07.06.2015 01:15
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
Принципы ООП в JavaScript
Принципы ООП в JavaScript
Парадигма объектно-ориентированного программирования имеет 4 основных принципа,
Пройдите собеседование по Angular: Общие вопросы и ответы экспертов
Пройдите собеседование по Angular: Общие вопросы и ответы экспертов
Можете ли вы объяснить разницу между ngOnInit и конструктором в Angular?
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Типы ввода HTML: Лучшие практики и советы
Типы ввода HTML: Лучшие практики и советы
HTML, или HyperText Markup Language , является стандартным языком разметки, используемым для создания веб-страниц. Типы ввода HTML - это различные...
415
4
122 243
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

Я делаю это так, что у меня есть пустой репозиторий Git на моем сервере развертывания, куда я отправляю изменения. Затем я вхожу на сервер развертывания, перехожу в каталог документации веб-сервера и выполняю git pull. Я не использую никаких ловушек, чтобы попытаться сделать это автоматически, это кажется больше проблемой, чем того стоит.

В случае ошибок в новом коде, вы сбрасываете для каждой фиксации или для всего извлечения? (Или возможно только 1?)

Rudie 27.09.2010 17:19

@Rudie: Если вам нужно откатить изменения на сервере развертывания, вы можете использовать git reset для возврата между изменениями последний (все коммиты, а не только весь запрос). Если вам нужно откатить что-то конкретное, не последнее, то вы можете использовать git revert, но его, вероятно, следует использовать только в экстренных случаях (git revert создает новую фиксацию, которая отменяет эффект некоторой предыдущей фиксации).

Greg Hewgill 27.09.2010 22:06

Просто из любопытства: как вы думаете, почему хуки могут доставить больше хлопот, чем они того стоят?

Rijk 13.03.2012 20:29

@Rijk: при использовании для этого хуков фактический каталог документации веб-сервера изменяется автоматически в фоновом режиме. Вход в систему позволяет мне лучше контролировать, когда именно вносятся изменения в каталог документов. Кроме того, когда что-то идет не так, легче исправить. Хуки могут быть более подходящими, если коммиттеры не имеют достаточного доступа для входа на веб-сервер.

Greg Hewgill 13.03.2012 22:00

Итак, ваша фактическая папка webapp также является репозиторием .git? А как насчет папки .git, она видна внешнему миру?

Fernando 25.07.2014 19:31

@ Фернандо: В моем случае, да, здесь нет ничего секретного. Однако для многих типов приложений вы можете захотеть поместить каталог .git в другое место (с GIT_DIR или GIT_WORK_TREE).

Greg Hewgill 26.07.2014 00:16

Да, спасибо. Например, просто скрыть .git через apache conf.

Fernando 26.07.2014 00:28

Похоже, у вас на сервере должно быть две копии. Пустая копия, которую вы можете нажимать / извлекать, из которой вы будете отправлять свои изменения, когда вы закончите, а затем вы должны клонировать ее в свой веб-каталог и настроить cronjob для обновления git pull из вашего веб-каталога каждый день или так.

Вы могли бы настроить ловушку git, которая, когда, скажем, совершается фиксация, называя «стабильную» ветвь, она извлекает изменения и применяет их к сайту PHP. Большой недостаток заключается в том, что у вас не будет особого контроля, если что-то пойдет не так, и это увеличит время вашего тестирования - но вы можете получить представление о том, сколько работы потребуется, когда вы объедините, скажем, ваша магистральная ветка в стабильную ветку, чтобы знать сколько конфликтов у вас май. Важно следить за любыми файлами, относящимися к конкретному сайту (например, файлами конфигурации), если только вы не собираетесь запускать только один сайт.

В качестве альтернативы, вы пытались вместо этого разместить изменение на сайте?

Для получения информации о хуках git см. Документацию githooks.

Ответ принят как подходящий

Я нашел этот сценарий на этот сайт, и, похоже, он работает довольно хорошо.

  1. Скопируйте каталог .git на свой веб-сервер
  2. В локальной копии измените файл .git / config и добавьте свой веб-сервер в качестве удаленного:

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. На сервере замените .git / hooks / post-update на этот файл (в ответе ниже)

  4. Добавляем доступ на выполнение к файлу (опять же, на сервере):

    chmod +x .git/hooks/post-update
    
  5. Теперь просто отправьте локально на свой веб-сервер, и он должен автоматически обновить рабочую копию:

    git push production
    

Убедитесь, что у вас есть политика .htaccess, которая защищает каталог .git от чтения. Кто-то, кто чувствует себя так, будто погружается в URL, мог бы потрудиться со всем исходным кодом, если он доступен.

Jeff Ferland 11.05.2010 01:41

В качестве альтернативы просто сделайте общедоступный каталог подкаталогом репозитория git. Тогда у вас могут быть личные файлы, и вы можете быть уверены, что они не станут общедоступными.

tlrobinson 08.06.2010 23:54

Не уверен, что понимаю это. Где мне создать свое первое репозиторий git, на рабочем веб-сервере или на тестовом веб-сервере?

Eric Martindale 23.06.2010 08:55

Эта ссылка мертва. есть еще ссылка на файл пост-обновления?

Robert Hurst 28.07.2010 03:27

Если вы используете подмодули, вы можете добавить git submodule update --init --recursive в сценарий post-update.

Eric 03.01.2011 00:59

Мне нравится идея сделать общедоступный каталог подкаталогом. Я думаю, что могу просто создать символическую ссылку в моем каталоге / var / www на каталог / public в моем репо.

freedrull 14.02.2011 00:48

Мне это нравится, но пользователь, с которым вы сталкиваетесь, должен иметь правильный доступ к htdocs. Это, безусловно, пользователь git. Как тебе это удается? Вы помещаете пользователя git в группу www-pub и даете этой группе разрешение на запись в / path / htdoc / *?

gagarine 05.04.2011 16:53

Возможно, мне что-то не хватает, но вы бы не хотели, чтобы ваш производственный сервер (-ы) был тянуть из ветки producttion главного репозитория git. Я предполагаю, что у OP только один сервер? Обычно я заставляю свой сервер непрерывной интеграции выполнять развертывание моего сайта (выполняя некоторые тесты перед развертыванием).

Adam Gent 16.09.2011 15:15

Выполнение этих шагов из репозитория, в котором уже есть последовательность коммитов; сначала вы не можете нажать, потому что главная ветвь уже извлечена. Затем, если вы проверяете альтернативную ветку на пульте дистанционного управления, только разные файлы извлекаются в рабочий каталог. Я ожидал, что хук сбросит настройки - это сложно для меня

barrymac 12.10.2011 14:15

Нужно добавить еще один шаг, чтобы разрешить нажатие на удаленный, добавлю к ответу

barrymac 12.10.2011 14:27

Это не очень хорошо работает с гитолитом из-за следующей строки: die "$ repo заканчивается косой чертой; мне это не нравится \ n" if $ repo = ~ / \ / $ /;

olive 20.10.2011 21:32

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

Antony 26.02.2012 09:36

@Antony Вот для чего нужен хук после обновления на стороне сервера - он заботится об этом автоматически при нажатии

Kyle Cronin 26.02.2012 09:39

Когда используются подмодули - они все равно будут содержать .git - верно?

Stann 04.05.2012 22:40

Если у вас порт ssh не 22, используйте следующий синтаксис: url = ssh: // user @ server: 44000 / home / fold / er / .git

Laurent Debricon 12.12.2012 17:26

Вам стоит взглянуть на это очень тривиальное решение: danbarber.me/using-git-for-deployment

Matthieu Lucas 31.01.2013 08:45

Если вы встретите ошибку отказ от обновления извлеченной ветки, вы можете решить ее, запустив git config receive.denyCurrentBranch ignore на сервере.

Kir Novak 24.11.2015 11:04

По сути, все, что вам нужно сделать, это следующее:

server = $1
branch = $2
git push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"

У меня есть эти строки в моем приложении как исполняемый файл под названием deploy.

Поэтому, когда я хочу выполнить развертывание, я набираю ./deploy myserver mybranch.

См. мой ответ, как решить проблему, если вам нужен другой закрытый ключ или имя пользователя для ssh

Karussell 26.11.2011 20:22

Это решение быстрее моего собственного при развертывании на нескольких серверах! Просто нажмите на основное репо и вытяните из него параллельно. А если вы не хотите или не можете развертывать свои ключи для каждого экземпляра, используйте ключевой агент! ssh -A ...

Karussell 31.10.2012 14:13

Было бы проще, если бы вы включили руководство по настройке ключей SSH, на которые этот ответ полагается, чтобы работать «без проблем».

Hengjie 31.10.2012 15:41

Следует избегать использования git pull для автоматического развертывания, поскольку его часть слияния может потребовать ручной очистки в случае возникновения каких-либо конфликтов.

Quinn Comendant 14.04.2015 03:37

Используя файл пост-обновление ниже:

  1. Скопируйте каталог .git на свой веб-сервер
  2. В локальной копии измените файл .git / config и добавьте свой веб-сервер в качестве удаленного:

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. На сервере замените .git / hooks / post-update файлом ниже

  4. Добавляем доступ на выполнение к файлу (опять же, на сервере):

    chmod +x .git/hooks/post-update
    
  5. Теперь просто отправьте локально на свой веб-сервер, и он должен автоматически обновить рабочую копию:

    git push production
    
#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update". 
git-update-server-info 
is_bare=$(git-config --get --bool core.bare) 
if [ -z "$is_bare" ]
then
      # for compatibility's sake, guess
      git_dir_full=$(cd $GIT_DIR; pwd)
      case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi 
update_wc() {
      ref=$1
      echo "Push to checked out branch $ref" >&2
      if [ ! -f $GIT_DIR/logs/HEAD ]
      then
             echo "E:push to non-bare repository requires a HEAD reflog" >&2
             exit 1
      fi
      if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
      then
             wc_dirty=0
      else
             echo "W:unstaged changes found in working copy" >&2
             wc_dirty=1
             desc = "working copy"
      fi
      if git diff-index --cached HEAD@{1} >/dev/null
      then
             index_dirty=0
      else
             echo "W:uncommitted, staged changes found" >&2
             index_dirty=1
             if [ -n "$desc" ]
             then
                   desc = "$desc and index"
             else
                   desc = "index"
             fi
      fi
      if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
      then
             new=$(git rev-parse HEAD)
             echo "W:stashing dirty $desc - see git-stash(1)" >&2
             ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
             git-update-ref --no-deref HEAD HEAD@{1}
             cd $GIT_WORK_TREE
             git stash save "dirty $desc before update to $new";
             git-symbolic-ref HEAD "$ref"
             )
      fi 
      # eye candy - show the WC updates :)
      echo "Updating working copy" >&2
      (cd $GIT_WORK_TREE
      git-diff-index -R --name-status HEAD >&2
      git-reset --hard HEAD)
} 
if [ "$is_bare" = "false" ]
then
      active_branch=`git-symbolic-ref HEAD`
      export GIT_DIR=$(cd $GIT_DIR; pwd)
      GIT_WORK_TREE=${GIT_WORK_TREE-..}
      for ref
      do
             if [ "$ref" = "$active_branch" ]
             then
                   update_wc $ref
             fi
      done
fi

Боже ... просто напишите этот скрипт на языке, который вы используете для разработки, будь то php, python, groovy или что-то еще! Я никогда не понимал этой любви к сценариям оболочки, которые имеют (субъективно) довольно странный синтаксис и так мало функциональных возможностей.

dVaffection 10.11.2014 07:55

@dVaffection в любом случае вы собираетесь писать команды оболочки, если используете git. поэтому вместо того, чтобы писать сценарий на другом языке и постоянно переключаться между этим языком и оболочкой. написание всего этого в оболочке кажется логичным, не так ли?

Abderrahmane TAHRI JOUTI 14.01.2016 13:44

Мне также пришлось выполнить git config receive.denyCurrentBranch updateInstead на сервере, чтобы он принял push. Я думаю, это потому, что ветка была проверена?

stackPusher 30.03.2017 18:43

После множества неудачных запусков и тупиков я наконец смог развернуть код веб-сайта с помощью всего лишь «git push удаленный» благодаря эта статья.

Сценарий автора после обновления состоит всего из одной строки, и его решение не требует конфигурации .htaccess, чтобы скрыть репозиторий Git, как это делают некоторые другие.

Пара камней преткновения, если вы развертываете это на инстансе Amazon EC2;

1) Если вы используете sudo для создания чистого целевого репозитория, вам нужно изменить владельца репо на пользователя ec2, иначе push не удастся. (Попробуйте "chown ec2-user: ec2-user репо.")

2) Push не удастся, если вы не настроите заранее расположение вашего amazon-приватный ключ.pem, либо в / etc / ssh / ssh_config в качестве параметра IdentityFile, либо в ~ / .ssh / config с использованием параметра «[Host] - HostName - IdentityFile - User »описание макета здесь ...

... ОДНАКО, если Host настроен в ~ / .ssh / config и отличается от HostName, Git push завершится ошибкой. (Вероятно, это ошибка Git)

Я выполнил шаги из упомянутой вами статьи, и все сработало как шарм. Мне только интересно, есть ли какие-то недостатки, касающиеся безопасности или стабильности. Есть какие-нибудь советы по этому поводу?

xlttj 07.12.2011 02:43

Xl-t: Предполагая, что вы используете Git поверх SSH, я бы сказал, что опасность заключается в ошибке с Git. Вы можете спросить автора статьи; он заканчивает его словами «Вопросы и предложения приветствуются». Моя текущая (безумная) стратегия репликации - использовать Transmit by Panic Software.

Earl Zedd 07.12.2011 21:21

В связанной статье есть одно важное требование при использовании хуков. Перехватчики завершатся ошибкой, если .git находится в той же схеме именования, что и рабочий каталог. т.е. / foo / bar (рабочий каталог) и /foo/bar.git (репозиторий barebone git). Поэтому убедитесь, что вы переименовали / foo / bar во что-то другое, например, /foo/bar.live или / foo / blah Ну, если вам интересно, точное сообщение об ошибке, которое вы получите, если ваш рабочий каталог имеет то же имя, что и репозиторий barebone - «удаленный: фатальный: не удалось вернуться в исходный cwd: нет такого файла или каталога»

Antony 26.02.2012 11:15

Я не понимаю, зачем вам нужен хук после развертывания для запуска. Отправка изменений кода в удаленное репо означает, что удаленное репо обновлено. Что мне не хватает?

Charlie Schliesser 30.06.2012 00:12

@CharlieS вам не хватает того, что git не позволит вам отправить ветку в репозиторий, в котором эта ветка проверена. В этом случае (ИМХО, очень хороший) ответ состоит в том, чтобы иметь два репозитория: голое репо, которое вы нажимаете, и второе репо, рабочий каталог которого обновляется с помощью крючка, когда голое репо отправляется.

Ben Hughes 16.02.2013 14:27

Отличный ответ. Намного чище, чем все, что я нашел

Ben Hughes 16.02.2013 14:28

Самое простое решение. Это должен быть ответ, получивший наибольшее количество голосов и принятых.

Oliver Angelil 06.07.2017 19:11

Не устанавливайте git на сервер и не копируйте туда папку .git. чтобы обновить сервер из клона git, вы можете использовать следующую команду:

git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project

Возможно, вам придется удалить файлы, которые были удалены из проекта.

Это копирует все зарегистрированные файлы. rsync использует ssh, который в любом случае установлен на сервере.

Чем меньше программного обеспечения вы установили на сервере, тем он безопаснее и тем проще управлять его конфигурацией и документировать ее. также нет необходимости хранить полный клон git на сервере. это только усложняет защиту всего должным образом.

Одно предостережение: он синхронизирует файлы, которые есть в вашем рабочем каталоге. Я думаю, что этого можно избежать, используя скрипт, который хранит текущие изменения, очищает все, развертывает, а затем восстанавливает тайник.

mateusz.fiolka 23.07.2012 00:23

Серверы мужские?

Ian Warburton 27.03.2017 22:56

Учитывая среду, в которой несколько разработчиков имеют доступ к одному и тому же репозиторию, следующие рекомендации могут помочь.

Убедитесь, что у вас есть группа unix, к которой принадлежат все разработчики, и передайте ей право собственности на репозиторий .git.

  1. В .git / config репозитория сервера установите sharedrepository = true. (Это говорит git о разрешении нескольких пользователей, что необходимо для коммитов и развертывания.

  2. Установите одинаковую umask для каждого пользователя в их файлах bashrc - 002 - хорошее начало

Легкомысленный до - это не зависящие от языка хуки просто добавь воды git для автоматизации развертывания с помощью git push. Он также позволяет настраивать хуки запуска / остановки для перезапуска веб-сервера, разогрева кеша и т. д.

Https://github.com/mpalmer/giddyup

Проверьте Примеры.

Обновление: сейчас я использую решение Ллойд Мур с ключевым агентом ssh -A .... Направление в основное репо и затем параллельное извлечение из него со всех ваших машин немного быстрее и требует меньше настроек на этих машинах.


Не вижу здесь этого решения. просто нажмите через ssh, если на сервере установлен git.

Вам понадобится следующая запись в вашем локальном .git / config

[remote "amazon"]
    url = amazon:/path/to/project.git
    fetch = +refs/heads/*:refs/remotes/amazon/*

Но что там с amazon:? В вашем локальном ~ / .ssh / config вам нужно будет добавить следующую запись:

Host amazon
    Hostname <YOUR_IP>
    User <USER>
    IdentityFile ~/.ssh/amazon-private-key

Теперь ты можешь вызвать

git push amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'

(Кстати: /path/to/project.git отличается от фактического рабочего каталога / пути / к / проекту)

Я закончил тем, что создал свой собственный элементарный инструмент развертывания, который автоматически извлекал бы новые обновления из репозитория - https://github.com/jesalg/SlimJim - в основном он слушает github post-receive-hook и использует прокси для запуска скрипта обновления.

Мы используем капистрано для управления развертыванием. Мы создаем capistrano для развертывания на промежуточном сервере, а затем запускаем rsync со всем нашим сервером.

cap deploy
cap deploy:start_rsync (when the staging is ok)

С capistrano мы можем легко откатиться в случае ошибки

cap deploy:rollback
cap deploy:start_rsync

Интегрировали ли вы живое развертывание через rsync в capistrano?

Martin Abraham 19.09.2014 16:53

Мой взгляд на решение Христиане.

git archive --prefix=deploy/  master | tar -x -C $TMPDIR | rsync $TMPDIR/deploy/ --copy-links -av username@server.com:/home/user/my_app && rm -rf $TMPDIR/deploy
  • Архивирует основную ветку в tar
  • Извлекает tar-архив в каталог развертывания в системной временной папке.
  • rsync превращается в сервер
  • удалить каталог развертывания из временной папки.

Я использую следующее решение от toroid.org, которое имеет более простой скрипт перехвата.

На сервере:

$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/

И устанавливаем ловушку на сервер:

$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
GIT_WORK_TREE=/var/www/www git clean -f -d # clean directory from removed files

$ chmod +x hooks/post-receive

На вашем клиенте:

$ mkdir website && cd website
$ git init
Initialized empty Git repository in /home/ams/website/.git/
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."

$ git remote add web ssh://server.example.org/home/ams/website.git
$ git push web +master:refs/heads/master

Затем, чтобы опубликовать, просто введите

$ git push web

На сайте есть полное описание: http://toroid.org/ams/git-website-howto

Таким образом не удаляйте существующие файлы в репозитории.

RusAlex 28.04.2015 17:34

Почему git push web +master:refs/heads/master, а не просто git push web master?

Matthieu Moy 29.04.2015 10:00

Git config --local receive.denyCurrentBranch updateInstead

Добавлено в Git 2.3, это может быть хорошей возможностью: https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

Вы устанавливаете его в репозитории сервера, и он также обновляет рабочее дерево, если оно чистое.

В 2.4 были внесены дальнейшие улучшения с Крюк push-to-checkout и обработка нерожденных веток.

Пример использования:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Выход:

a
b

У этого есть следующие недостатки, упомянутые в анонсе GitHub:

  • На вашем сервере будет каталог .git, содержащий всю историю вашего проекта. Вероятно, вы захотите дополнительно убедиться, что он не может быть доставлен пользователям!
  • Во время развертывания пользователи могут на мгновение обнаружить сайт в несогласованном состоянии, с некоторыми файлами в старой версии, а другими в новой версии или даже с наполовину записанными файлами. Если это проблема для вашего проекта, push-to-deploy, вероятно, не для вас.
  • Если вашему проекту нужен этап «сборки», вам нужно будет настроить его явно, возможно, через githooks.

Но все эти моменты выходят за рамки Git, и о них нужно позаботиться с помощью внешнего кода. В этом смысле это вместе с хуками Git является окончательным решением.

Чтобы установить его, запустите эту команду: 'git config receive.denyCurrentBranch updateInstead' в терминале

stackPusher 30.03.2017 18:44

В качестве дополнительного ответа я хотел бы предложить альтернативу. Я использую git-ftp, и он отлично работает.

Https://github.com/git-ftp/git-ftp

Простота использования, введите только:

git ftp push

И git автоматически загрузит файлы проекта.

С уважением

Для сценария развертывания

В нашем сценарии мы храним код на github / bitbucket и хотим развернуть его на действующих серверах. В этом случае у нас работает следующая комбинация (это ремикс на высоко оцененные ответы здесь):

  1. Скопируйте каталог .git на свой веб-сервер
  2. На вашей локальной копии git remote add live ssh://user@host:port/folder
  3. На пульте: git config receive.denyCurrentBranch ignore
  4. На удаленном: nano .git/hooks/post-receive и добавьте это содержимое:

    #!/bin/sh GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f

  5. На пульте: chmod +x .git/hooks/post-receive

  6. Теперь можно туда пихать с git push live

Ноты

  • Это решение работает со старыми версиями git (протестировано с 1.7 и 1.9)
  • Вам нужно сначала нажать на github / bitbucket, чтобы у вас было последовательное репо в реальном времени.
  • Если ваша папка .git находится в корне документа, убедитесь, что вы скрыли ее извне, добавив в .htaccess (источник):

    RedirectMatch 404 /\..*$

Я использую два решения для крючка после получения:

РАЗВЕРТЫВАНИЕ РЕШЕНИЯ 1

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 1 

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi
done

РАЗВЕРТЫВАНИЕ РЕШЕНИЯ 2

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 2

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    export GIT_TEMP_DIR1=/tmp/deploy1
    export GIT_TEMP_DIR2=/tmp/deploy2
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo "GIT TEMP DIR1:  $GIT_TEMP_DIR1/"
    echo "GIT TEMP DIR2:  $GIT_TEMP_DIR2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR1; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR1/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET1/.
        rsync $GIT_TEMP_DIR1/. -v -q --delete --delete-after -av $GIT_TARGET1/.
        rm -rf $GIT_TEMP_DIR1
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR2/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET2/.
        rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/.
        rm -rf $GIT_TEMP_DIR2
    fi
done

Оба решения основаны на более ранних решениях, доступных в этом потоке.

Обратите внимание BRANCH_REGEX = '^ $ {GIT_BRANCH1} .$ ' фильтры для названий веток, соответствующих "master" "или строка" dev * "и развертывает дерево работ, если отправленная ветвь совпадает. Это позволяет развернуть версию разработчика и основную версию в разных местах.

РАЗВЕРНУТЬ РЕШЕНИЕ 1 удаляет только файлы, которые являются частью репо и были удалены фиксацией. Это быстрее, чем Deployment Solution 2.

DEPLOY SOLUTION 2 имеет то преимущество, что он удалит любые новые файлы из производственного каталога, который был добавлен на стороне сервера, независимо от того, был ли он добавлен в репо или нет. Это всегда будет чистый обман репо. Это медленнее, чем решение для развертывания 1.

Другие вопросы по теме