Est-il possible de déployer un site Web en utilisant git push
? J'ai un pressentiment que cela a quelque chose à voir avec l'utilisation de hooks git pour effectuer un git reset --hard
côté serveur, mais comment pourrais-je y parvenir?
Est-il possible de déployer un site Web en utilisant git push
? J'ai un pressentiment que cela a quelque chose à voir avec l'utilisation de hooks git pour effectuer un git reset --hard
côté serveur, mais comment pourrais-je y parvenir?
Réponses:
J'ai trouvé ce script sur ce site et il semble très bien fonctionner.
Sur votre copie locale, modifiez votre fichier .git / config et ajoutez votre serveur Web en tant que télécommande:
[remote "production"]
url = username@webserver:/path/to/htdocs/.git
Sur le serveur, remplacez .git / hooks / post-update par ce fichier (dans la réponse ci-dessous)
Ajoutez un accès d'exécution au fichier (encore une fois, sur le serveur):
chmod +x .git/hooks/post-update
Maintenant, il suffit de pousser localement vers votre serveur Web et il devrait automatiquement mettre à jour la copie de travail:
git push production
Utilisation du fichier post-mise à jour ci-dessous:
Sur votre copie locale, modifiez votre fichier .git / config et ajoutez votre serveur Web en tant que télécommande:
[remote "production"]
url = username@webserver:/path/to/htdocs/.git
Sur le serveur, remplacez .git / hooks / post-update par le fichier ci-dessous
Ajoutez un accès d'exécution au fichier (encore une fois, sur le serveur):
chmod +x .git/hooks/post-update
Maintenant, il suffit de pousser localement vers votre serveur Web et il devrait automatiquement mettre à jour la copie de travail:
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
Après de nombreux faux départs et impasses, je suis enfin capable de déployer du code de site web avec juste "git push remote " grâce à cet article .
Le script post-mise à jour de l'auteur ne comprend qu'une seule ligne et sa solution ne nécessite pas de configuration .htaccess pour masquer le dépôt Git comme d'autres le font.
Quelques pierres d'achoppement si vous déployez cela sur une instance Amazon EC2;
1) Si vous utilisez sudo pour créer le référentiel de destination nu, vous devez changer le propriétaire du référentiel en ec2-user ou le push échouera. (Essayez "chown ec2-user: ec2-user repo .")
2) Le push échouera si vous ne préconfigurez pas l'emplacement de votre .pem amazon-private-key , soit dans / etc / ssh / ssh_config en tant que paramètre IdentityFile, soit dans ~ / .ssh / config en utilisant le "[ Hôte] - HostName - IdentityFile - Présentation de l'utilisateur "décrite ici ...
... TOUTEFOIS, si l'hôte est configuré dans ~ / .ssh / config et différent de HostName, le push Git échouera. (C'est probablement un bug Git)
n'installez pas git sur un serveur ou copiez-y le dossier .git. pour mettre à jour un serveur à partir d'un clone git, vous pouvez utiliser la commande suivante:
git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project
vous devrez peut-être supprimer les fichiers qui ont été supprimés du projet.
cela copie tous les fichiers archivés. rsync utilise ssh qui est de toute façon installé sur un serveur.
moins vous avez installé de logiciel sur un serveur, plus il est sécurisé et plus il est facile de gérer sa configuration et de la documenter. il n'est pas non plus nécessaire de conserver un clone git complet sur le serveur. cela ne fait que rendre plus complexe de sécuriser tout correctement.
En substance, tout ce que vous devez faire est le suivant:
server = $1
branch = $2
git push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"
J'ai ces lignes dans ma demande en tant qu'exécutable appelé deploy
.
donc quand je veux faire un déploiement je tape ./deploy myserver mybranch
.
ssh -A ...
git pull
doit être évitée pour les déploiements automatisés car la partie de fusion pourrait nécessiter un nettoyage manuel en cas de conflit.
La façon dont je le fais est que j'ai un référentiel Git nu sur mon serveur de déploiement où je pousse les modifications. Ensuite, je me connecte au serveur de déploiement, je passe au répertoire de documentation du serveur Web et je fais un pull git. Je n'utilise pas de crochets pour essayer de le faire automatiquement, cela semble plus difficile que cela ne vaut.
git reset
pour revenir en arrière parmi les dernières modifications (toutes les validations, pas seulement l'ensemble). Si vous devez annuler quelque chose de spécifique qui n'est pas le dernier commit, vous pouvez l'utiliser, git revert
mais cela devrait probablement être utilisé uniquement en cas d'urgence ( git revert
crée un nouveau commit qui annule l'effet de certains commit précédents).
git config --local receive.denyCurrentBranch updateInstead
Ajouté dans Git 2.3, cela pourrait être une bonne possibilité: https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155
Vous le définissez sur le référentiel du serveur et il met également à jour l'arborescence de travail s'il est propre.
Il y a eu d'autres améliorations dans 2.4 avec le push-to-checkout
crochet et la manipulation des branches à naître .
Exemple d'utilisation:
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
Production:
a
b
Cela présente les lacunes suivantes mentionnées dans l'annonce GitHub :
Mais tous ces points sont hors de portée de Git et doivent être pris en charge par un code externe. En ce sens, cela, avec les crochets Git, est la solution ultime.
Mise à jour: j'utilise maintenant la solution Lloyd Moore avec l'agent clé ssh -A ...
. Pousser vers un référentiel principal puis le retirer en parallèle de toutes vos machines est un peu plus rapide et nécessite moins de configuration sur ces machines.
Ne pas voir cette solution ici. il suffit de pousser via ssh si git est installé sur le serveur.
Vous aurez besoin de l'entrée suivante dans votre .git / config local
[remote "amazon"]
url = amazon:/path/to/project.git
fetch = +refs/heads/*:refs/remotes/amazon/*
Mais bon, avec quoi ça amazon:
? Dans votre ~ / .ssh / config local, vous devrez ajouter l'entrée suivante:
Host amazon
Hostname <YOUR_IP>
User <USER>
IdentityFile ~/.ssh/amazon-private-key
maintenant tu peux appeler
git push amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'
(BTW: /path/to/project.git est différent du répertoire de travail réel / path / to / project)
Dans notre scénario, nous stockons le code sur github / bitbucket et voulons déployer sur des serveurs en direct. Dans ce cas, la combinaison suivante fonctionne pour nous (c'est-à-dire un remix des réponses très appréciées ici) :
.git
répertoire sur votre serveur Webgit remote add live ssh://user@host:port/folder
git config receive.denyCurrentBranch ignore
À distance: nano .git/hooks/post-receive
et ajoutez ce contenu:
#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f
Sur la télécommande: chmod +x .git/hooks/post-receive
git push live
Si votre .git
dossier est dans la racine du document, assurez-vous de le cacher de l'extérieur en ajoutant à .htaccess
( source ):
RedirectMatch 404 /\..*$
Nous utilisons capistrano pour gérer le déploiement. Nous construisons capistrano pour le déployer sur un serveur intermédiaire, puis exécutons un rsync avec l'ensemble de notre serveur.
cap deploy
cap deploy:start_rsync (when the staging is ok)
Avec capistrano, nous pouvons faire un rollback facile en cas de bug
cap deploy:rollback
cap deploy:start_rsync
Giddyup sont des crochets git gnostiques juste pour ajouter de l'eau pour automatiser le déploiement via git push. Il vous permet également d'avoir des crochets de démarrage / arrêt personnalisés pour redémarrer le serveur Web, réchauffer le cache, etc.
https://github.com/mpalmer/giddyup
Découvrez des exemples .
On dirait que vous devriez avoir deux copies sur votre serveur. Une copie nue, à partir de laquelle vous pouvez pousser / tirer, à partir de laquelle vous pousserez vos modifications lorsque vous aurez terminé, puis vous clonerez cela dans votre répertoire Web et configurerez un cronjob pour mettre à jour git pull à partir de votre répertoire Web tous les jours ou donc.
On pourrait imaginer mettre en place un hook git qui, quand on dit qu'un commit est fait pour dire la branche "stable", il tirera les changements et les appliquera au site PHP. Le gros inconvénient est que vous n'aurez pas beaucoup de contrôle si quelque chose ne va pas et cela ajoutera du temps à vos tests - mais vous pouvez avoir une idée de la quantité de travail qui sera impliquée lorsque vous fusionnerez, par exemple, votre branche de tronc dans la branche stable pour savoir combien de conflits vous pouvez rencontrer. Il sera important de garder un œil sur tous les fichiers spécifiques au site (par exemple, les fichiers de configuration), sauf si vous avez uniquement l'intention d'exécuter un seul site.
Sinon, avez-vous plutôt envisagé de pousser le changement sur le site?
Pour plus d'informations sur les hooks git, consultez la documentation des githooks .
Ma vision de la solution chrétienne .
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
J'utilise la solution suivante de toroid.org , qui a un script de hook plus simple.
sur le serveur:
$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/
et installez le crochet sur le serveur:
$ 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
sur votre client:
$ 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
puis pour publier, tapez simplement
$ git push web
Il y a une description complète sur le site: http://toroid.org/ams/git-website-howto
git push web +master:refs/heads/master
au lieu de juste git push web master
?
Comme réponse complémentaire, je voudrais proposer une alternative. J'utilise git-ftp et cela fonctionne bien.
https://github.com/git-ftp/git-ftp
Facile à utiliser, tapez uniquement:
git ftp push
et git téléchargera automatiquement les fichiers du projet.
Cordialement
Dans un environnement où plusieurs développeurs accèdent au même référentiel, les instructions suivantes peuvent vous aider.
Assurez-vous que vous disposez d'un groupe Unix auquel tous les développeurs appartiennent et donnez la propriété du référentiel .git à ce groupe.
Dans le .git / config du référentiel du serveur, définissez sharedrepository = true. (Cela indique à git d'autoriser plusieurs utilisateurs, ce qui est nécessaire pour les validations et le déploiement.
définissez le umask de chaque utilisateur dans leurs fichiers bashrc pour être le même - 002 est un bon début
J'ai fini par créer mon propre outil de déploiement rudimentaire qui retirerait automatiquement les nouvelles mises à jour du dépôt - https://github.com/jesalg/SlimJim - En gros, il écoute le github post-receive-hook et utilise un proxy pour déclencher un script de mise à jour.
J'utilise deux solutions pour le crochet post-réception:
DÉPLOYER LA SOLUTION 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
DÉPLOYER LA SOLUTION 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
Les deux solutions sont basées sur des solutions antérieures disponibles dans ce fil.
Notez que BRANCH_REGEX = '^ $ {GIT_BRANCH1}. $ 'filtre les noms de branche correspondant à la chaîne "master " ou "dev *" et déploie l'arborescence de travail, si la branche poussée correspond. Cela permet de déployer une version de développement et une version principale à différents endroits.
DEPLOY SOLUTION 1 supprime uniquement les fichiers, qui font partie du référentiel, et a été supprimé par une validation. Il est plus rapide que la solution de déploiement 2.
DEPLOY SOLUTION 2 a l'avantage de supprimer tous les nouveaux fichiers du répertoire de production, qui a été ajouté côté serveur, qu'il ait été ajouté au référentiel ou non. Ce sera toujours dupe propre du repo. Il est plus lent que la solution de déploiement 1.