Est-il possible de déployer un site Web en utilisant git Push
? J'ai l'impression que cela a quelque chose à voir avec l'utilisation de git hooks pour exécuter un git reset --hard
sur le serveur, mais comment pourrais-je y parvenir?
J'ai trouvé ce script sur ce site et il semble fonctionner assez bien.
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 en exécution au fichier (à nouveau, sur le serveur):
chmod +x .git/hooks/post-update
Désormais, il suffit d'appuyer localement sur votre serveur Web pour qu'il mette automatiquement à jour la copie de travail:
git Push production
En utilisant le fichier post-update 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 en exécution au fichier (à nouveau, sur le serveur):
chmod +x .git/hooks/post-update
Désormais, il suffit d'appuyer localement sur votre serveur Web pour qu'il mette automatiquement à 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 peux enfin déployer le code de site Web avec juste "git Push à distance " grâce à cet article .
Le script post-mise à jour de l'auteur ne comporte qu'une ligne et sa solution ne nécessite pas de configuration .htaccess pour masquer le dépôt Git, contrairement à d'autres.
Quelques obstacles si vous déployez cela sur une instance Amazon EC2;
1) Si vous utilisez Sudo pour créer le référentiel de destination nue, vous devez changer le propriétaire du référentiel en ec2-user, sans quoi le push échouera. (Essayez "chown ec2-user: ec2-user repo .")
2) Le Push échouera si vous ne préconfigurez pas l'emplacement de votre clé privée Amazon . Pem, soit dans/etc/ssh./ssh_config en tant que paramètre IdentityFile ou dans ~/.ssh/config à l'aide de la présentation "[Host] - HostName - IdentityFile - User" décrite ici ...
Cependant, si l'hôte est configuré dans ~/.ssh/config et différent de HostName, Git Push échouera. (C'est probablement un bug de Git)
ne pas installer git sur un serveur ou copier le dossier .git. pour mettre à jour un serveur depuis un clone git, vous pouvez utiliser la commande suivante:
git ls-files -z | rsync --files-from - --copy-links -av0 . [email protected]:/var/www/project
vous devrez peut-être supprimer les fichiers supprimés du projet.
cela copie tous les fichiers archivés. rsync utilise de toute façon ssh qui est 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 complet de git sur le serveur. cela ne fait que rendre plus complexe la sécurisation correcte de tout.
En substance, tout ce que vous devez faire sont les suivants:
server = $1
branch = $2
git Push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"
J'ai ces lignes dans mon application en tant qu'exécutable appelé deploy
.
donc quand je veux faire un déploiement, je tape ./deploy myserver mybranch
.
Comme je le fais, j’ai un référentiel Git nu sur mon serveur de déploiement où les modifications Push. Ensuite, je me connecte au serveur de déploiement, je modifie le répertoire de documents du serveur Web et effectue une extraction git. Je n'utilise pas de crochets pour essayer de le faire automatiquement, cela semble être plus de problèmes que ça n'en vaut la peine.
receive.denyCurrentBranch updateInstead ajouté dans Git 2.3 est une possibilité.
Définissez-le sur le référentiel du serveur et il met également à jour l'arborescence de travail si elle est propre.
La version 2.4 a été améliorée avec le crochet Push-to-checkout
et le traitement des branches non encore nées .
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
Sortie:
a
b
Cela a les défauts suivants mentionnés sur l'annonce de GitHub :
Mais tous ces points sont hors de la portée de Git et doivent être gérés par un code externe. Donc, dans ce sens, ceci, avec les crochets Git, constitue la solution ultime.
Dans notre scénario, nous stockons le code sur github/bitbucket et souhaitons le déployer sur des serveurs en direct. Dans ce cas, la combinaison suivante fonctionne pour nous (c'est un remix des réponses les plus votées ici) :
.git
sur votre serveur Web.git remote add live ssh://user@Host:port/folder
git config receive.denyCurrentBranch ignore
Sur la télécommande: 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 dossier .git
se trouve dans la racine du document, assurez-vous de le masquer de l'extérieur en ajoutant à .htaccess
( source ):
RedirectMatch 404 /\..*$
Mise à jour: J'utilise maintenant Lloyd Moore solution avec l'agent de clé ssh -A ...
. Pousser vers un dépôt principal puis le sortir 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. Appuyez simplement sur 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 hé, qu'est-ce que c'est avec Amazon:
? Dans votre ~/.ssh/config local, vous devez 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 actuel/path/to/project)
Nous utilisons capistrano pour gérer déployer. Nous construisons capistrano pour le déploiement sur un serveur intermédiaire, puis pour exécuter un rsync avec l’ensemble de nos serveurs.
cap deploy
cap deploy:start_rsync (when the staging is ok)
Avec capistrano, on peut facilement revenir en arrière en cas de problème
cap deploy:rollback
cap deploy:start_rsync
Giddyup sont indépendants de la langue juste-ajouter-eau pour automatiser le déploiement via git Push. Il vous permet également d'avoir des points d'ancrage personnalisés pour démarrer/arrêter le serveur Web, réchauffer le cache, etc.
https://github.com/mpalmer/giddyup
Départ exemples .
On dirait que vous devriez avoir deux copies sur votre serveur. Une copie nue, à partir de laquelle vous pouvez appuyer/extraire, à partir de laquelle vous souhaitez appliquer vos modifications lorsque vous avez terminé, puis cloner cette information dans votre répertoire Web et configurer un travail cron pour mettre à jour git pull à partir de votre répertoire Web tous les jours ou alors.
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 hook 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, il suffit de taper
$ git Push web
Il y a une description complète sur le site: http://toroid.org/ams/git-website-howto
Comme réponse complémentaire, j'aimerais proposer une alternative. J'utilise git-ftp et cela fonctionne bien.
https://github.com/git-ftp/git-ftp
Facile à utiliser, seul le type:
git ftp Push
et git téléchargera automatiquement les fichiers du projet.
Cordialement
Mon point de vue sur chrétiens solution.
git archive --prefix=deploy/ master | tar -x -C $TMPDIR | rsync $TMPDIR/deploy/ --copy-links -av [email protected]:/home/user/my_app && rm -rf $TMPDIR/deploy
Vous pourriez éventuellement configurer un crochet git qui, lorsqu'un script est engagé, indique les branches "stables", il extrait les modifications et les applique au site PHP. Le gros inconvénient est que vous n’aurez pas beaucoup de contrôle en cas de problème, ce qui vous donnera plus de temps pour vos tests - mais vous pouvez avoir une idée de l’ampleur du travail que vous devrez effectuer lorsque vous fusionnerez, dites à votre branche de coffre dans la branche stable de savoir combien de conflits vous pouvez rencontrer. Il sera important de garder un œil sur tous les fichiers propres au site (par exemple, les fichiers de configuration), à moins que vous ne souhaitiez uniquement exécuter le site en question.
Sinon, avez-vous envisagé de modifier le site à la place?
Pour plus d'informations sur les crochets git, voir la documentation githooks .
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 avez un groupe unix auquel tous les développeurs appartiennent et donnez la propriété du référentiel .git à ce groupe.
Dans le fichier .git/config du référentiel du serveur, 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 ses fichiers bashrc pour qu'il soit identique - 002 est un bon début
J'ai fini par créer mon propre outil de déploiement rudimentaire qui extrairait automatiquement les nouvelles mises à jour du référentiel - 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 hook 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
DEPLOY 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 les filtres BRANCH_REGEX = '^ $ {GIT_BRANCH1}. $' pour les noms de branche correspondant à la chaîne "master " ou "dev *" et sont déployés. l'arbre de travail, si la branche poussée correspond. Cela permet de déployer une version dev et une version maître à différents endroits.
DEPLOY SOLUTION 1 ne supprime que les fichiers qui font partie du référentiel et a été supprimé par un commit. C'est plus rapide que la solution de déploiement 2.
DEPLOY SOLUTION 2 présente l’avantage de supprimer tous les nouveaux fichiers du répertoire de production ajouté sur le 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.