Чи можливо розгорнути веб-сайт за допомогою git push
? Я маю на увазі, що це має щось спільне з використанням git гаків для виконання git reset --hard
на серверній стороні, але як би я пішов про це?
Чи можливо розгорнути веб-сайт за допомогою git push
? Я маю на увазі, що це має щось спільне з використанням git гаків для виконання git reset --hard
на серверній стороні, але як би я пішов про це?
Відповіді:
Я знайшов цей скрипт на цьому сайті і, здається, він працює досить добре.
На локальній копії змініть файл .git / config та додайте веб-сервер як віддалений:
[remote "production"]
url = username@webserver:/path/to/htdocs/.git
На сервері замініть .git / hooks / post-update цим файлом (у відповіді нижче)
Додайте виконавчий доступ до файлу (знову ж таки, на сервері):
chmod +x .git/hooks/post-update
Тепер просто локально натисніть на ваш веб-сервер, і він повинен автоматично оновити робочу копію:
git push production
Використовуючи файл після оновлення нижче:
На локальній копії змініть файл .git / config та додайте веб-сервер як віддалений:
[remote "production"]
url = username@webserver:/path/to/htdocs/.git
На сервері замініть .git / hooks / post-update на файл нижче
Додайте виконавчий доступ до файлу (знову ж таки, на сервері):
chmod +x .git/hooks/post-update
Тепер просто локально натисніть на ваш веб-сервер, і він повинен автоматично оновити робочу копію:
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
Після багатьох помилкових стартів і тупиків я нарешті зможу розгорнути код веб-сайту за допомогою лише "git push remote " завдяки цій статті .
Авторський сценарій після оновлення триває лише один рядок, і його рішення не вимагає конфігурації .htaccess, щоб приховати репо-гіт Git, як це роблять деякі інші.
Кілька каменів спотикання, якщо ви розгортаєте це в екземплярі Amazon EC2;
1) Якщо ви використовуєте sudo для створення голого сховища призначення, вам доведеться змінити власника репо на користувача ec2, інакше натискання не вдасться. (Спробуйте "chown ec2-user: ec2-користувач repo .")
2) Натискання не вдасться, якщо ви не заздалегідь налаштуєте розташування свого amazon-private-key .pem, або в / etc / ssh / ssh_config як параметр IdentityFile або в ~ / .ssh / config, використовуючи "[ Хост] - HostName - IdentityFile - User "макет, описаний тут ...
... ЗАРАЗ, якщо Host налаштований у ~ / .ssh / config та відрізняється від HostName, натискання Git не вдасться. (Це, мабуть, помилка Git)
не встановлюйте git на сервер чи копіюйте туди папку .git. для оновлення сервера з git-клону можна скористатись такою командою:
git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project
можливо, доведеться видалити файли, видалені з проекту.
це копіює всі перевірені файли. rsync використовує ssh, який будь-коли встановлений на сервері.
чим менше програмного забезпечення встановлено на сервері, тим він захищеніший і тим простіше керувати його конфігурацією та документувати її. також не потрібно зберігати повний клон git на сервері. це лише робить його складнішим, щоб усе забезпечити належним чином.
По суті все, що вам потрібно зробити, це:
server = $1
branch = $2
git push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"
У моїй програмі є такі рядки, як названий виконуваний файл deploy
.
тому коли я хочу зробити розгортання, я набираю ./deploy myserver mybranch
.
ssh -A ...
git pull
слід уникати автоматичного розгортання , оскільки злиття частина може зажадати ручної очистки , якщо є якісь - або конфлікти.
Як я це роблю, у мене є голе сховище Git на моєму сервері розгортання, де я натискаю зміни. Потім я входжу на сервер розгортання, переходжу на фактичний каталог документів веб-сервера і виконую git pull. Я не використовую жодних гачків, щоб намагатися зробити це автоматично, це здається більшим клопотом, ніж варто.
git reset
для переміщення серед останніх змін (усі зобов’язання, а не лише весь потяг). Якщо вам потрібно скасувати щось конкретне, що не є останньою комісією, ви можете використовувати, git revert
але це, ймовірно, слід використовувати лише в надзвичайних ситуаціях ( git revert
створюється новий комітет, який скасовує ефект деяких попередніх зобов’язань).
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, і про них слід піклуватися зовнішнім кодом. Тож у цьому сенсі це разом із гачками Git - це остаточне рішення.
Оновлення: Зараз я використовую рішення Ллойда Мура з ключовим агентом 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'
(BTW: /path/to/project.git відрізняється від фактичного робочого каталогу / шляху / до / проекту)
У нашому сценарії ми зберігаємо код на github / bitbucket і хочемо розгорнути на живих серверах. У цьому випадку для нас працює наступна комбінація (це ремікс висококваліфікованих відповідей тут) :
.git
каталог на свій веб-серверgit remote add live ssh://user@host:port/folder
git config receive.denyCurrentBranch ignore
У віддаленому режимі: nano .git/hooks/post-receive
і додайте цей вміст:
#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f
На віддаленому: chmod +x .git/hooks/post-receive
git push live
Якщо ваша .git
папка знаходиться в корені документа, переконайтесь, що ви приховали її зовні, додавши до .htaccess
( джерело ):
RedirectMatch 404 /\..*$
Ми використовуємо capistrano для управління розгортанням. Ми будуємо capistrano для розгортання на сервері, а потім запускаємо rsync з усім нашим сервером.
cap deploy
cap deploy:start_rsync (when the staging is ok)
Завдяки capistrano ми можемо зробити легкий відкат у випадку помилок
cap deploy:rollback
cap deploy:start_rsync
Giddyup - це мовно-агностичні гачки з додаванням води для автоматизації розгортання за допомогою git push. Це також дозволяє мати спеціальні гачки для запуску / зупинки для перезавантаження веб-сервера, прогрівання кешу тощо.
https://github.com/mpalmer/giddyup
Перегляньте приклади .
Здається, що на вашому сервері має бути дві копії. Гола копія, яку ви можете натиснути / витягнути, і яка б підштовхнула ваші зміни, коли ви закінчите, і тоді ви будете клонувати це у свій веб-каталог і налаштувати cronjob для оновлення git pull зі свого веб-каталогу щодня або тому.
Можна, можливо, встановити гачок git, який, коли скажеться, що фіксація буде сказати "стабільну" гілку, вона потягне зміни та застосує їх до сайту PHP. Великий недолік - у вас не буде багато контролю, якщо щось піде не так, і це додасть часу вашому тестуванню - але ви можете отримати уявлення про те, скільки роботи буде задіяно, коли ви об’єднаєте, скажімо, ваша гілка стовбура в стійку гілку, щоб знати скільки конфліктів ви можете зіткнутися. Важливо слідкувати за будь-якими файлами, що мають особливий сайт (наприклад, файли конфігурації), якщо тільки ви не маєте наміру запускати лише один сайт.
Або ви замість цього намагалися змінити сайт?
Для отримання інформації про git hooks дивіться документацію на githooks .
Моє прийняти рішення християн .
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
Я використовую таке рішення від 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
git push web +master:refs/heads/master
замість просто git push web master
?
Як додаткову відповідь я хотів би запропонувати альтернативу. Я використовую git-ftp, і він працює чудово.
https://github.com/git-ftp/git-ftp
Простий у використанні, лише тип:
git ftp push
і git автоматично завантажить файли проекту.
З повагою
З огляду на середовище, де у вас є декілька розробників, які мають доступ до одного сховища, наступні вказівки можуть допомогти.
Переконайтеся, що у вас є група Unix, до якої належать усі розробники, і надайте право власності на сховище .git цій групі.
У .git / config серверного сховища встановлено sharedrepository = true. (Це повідомляє git, щоб дозволити декілька користувачів, які потрібні для комітетів та розгортання.
встановити umask кожного користувача у файлах bashrc таким самим - 002 - це хороший початок
Я в кінцевому підсумку створив власний інструмент рудиментарного розгортання, який автоматично знімав би нові оновлення з репо - https://github.com/jesalg/SlimJim - В основному він слухає github post-accept-hoke і використовує проксі для запуску оновити сценарій.
Я використовую два рішення для гачка після отримання:
РІШЕННЯ РОБОТИ 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 *", і розгортає робоче дерево, якщо натиснута гілка збігається. Це дає можливість розгорнути версію розробника та головну версію в різних місцях.
DEPLOY SOLUTION 1 видаляє лише файли, що входять до складу репо, і був видалений комітом. Це швидше, ніж рішення 2 для розгортання.
Перевага DEPLOY SOLUTION 2 полягає в тому, що він видалить будь-які нові файли з виробничого каталогу, який був доданий на стороні сервера, незалежно від того, додавали його в репортаж чи ні. Це буде завжди чистий дупе репо. Це повільніше, ніж рішення 1 для розгортання.