Разверните проект с помощью Git push - PullRequest
409 голосов
/ 11 ноября 2008

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

Ответы [ 19 ]

287 голосов
/ 29 ноября 2008

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

  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
    
77 голосов
/ 02 августа 2010

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

  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
59 голосов
/ 03 марта 2011

После многих фальстартов и тупиков, я наконец-то смог развернуть код сайта просто с помощью "git push remote " благодаря этой статье .

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

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

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

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

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

21 голосов
/ 24 августа 2011

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

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

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

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

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

12 голосов
/ 11 мая 2010

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

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

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

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

9 голосов
/ 11 ноября 2008

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

8 голосов

receive.denyCurrentBranch updateInstead добавлено в Git 2.3 возможно.

Установите его в хранилище сервера, а также обновит рабочее дерево, если оно чистое.

Произошли дальнейшие улучшения в версии 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, является окончательным решением.

5 голосов
/ 26 ноября 2011

Обновление: сейчас я использую решение Ллойда Мура с ключевым агентом 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 отличается от фактического рабочего каталога / path / to / project)

4 голосов
/ 29 ноября 2012

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

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

С Capistrano мы можем сделать простой откат в случае ошибки

cap deploy:rollback
cap deploy:start_rsync
4 голосов
/ 17 октября 2015

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

В нашем сценарии мы храним код в 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 ( source ):

    RedirectMatch 404 /\..*$

...