A Git hook allows you to execute custom scripts when an action occurs, such as when a commit or push is performed. Before I discovered git hooks, my deployment process consisted of pushing changes to my remote repository, SSH’ing into the server, navigating to the site directory, pulling the changes, and restarting the webserver. It wasn’t efficient at all and a waste of time doing that several times a day. I’ll explain how to set up a simple git hook making the deployment process a bit more effortless, but first I want to give credit to this how-to article which got me started.
In this example we’ll be deploying the production branch but it can be whatever branch name you want, and our site name will be called foo.
On the server
Initialize an empty git repo. This will act as the mediator.
mkdir -p /opt/git/foo.git cd /opt/git/tracfone.git git init --bare # no source files, only version control
post-receive hook which gets called after a push is complete.
#!/bin/bash SITE_NAME="Foo" SITE_PATH="/var/www/foo.com" BRANCH="production" echo "**** $SITE_NAME [post-receive] hook received." while read oldrev newrev ref do branch_received=`echo $ref | cut -d/ -f3` echo "**** Received [$branch_received] branch." # Making sure we received the branch we want. if [ $branch_received = $BRANCH ]; then cd $SITE_PATH # Unset to use current working directory. unset GIT_DIR echo "**** Pulling changes." git pull origin $BRANCH # Instead of pulling we can also do a checkout. : ' echo "**** Checking out branch." GIT_WORK_TREE=$SITE_PATH git checkout -f $BRANCH ' # Or we can also do a fetch and reset. : ' echo "**** Fetching and reseting." git fetch --all git reset --hard origin/$BRANCH ' else echo "**** Invalid branch, aborting." exit 0 fi done # [Restart/reload webserver stuff here] echo "**** Done." exec git-update-server-info
Make sure to make the hook executable.
chmod u+rwx /opt/git/foo.git/hooks/post-receive
On the client
Add the remote url.
git remote add production ssh://<username@<server ip>/opt/git/foo.git
Push the production branch.
git push production +production:refs/heads/production # Afterwards you can simply do git push production
It’s also possible to deploy to multiple servers, just add the remote urls in
[remote "production"] url = ssh://<username>@<server 1 ip>/opt/git/foo.git url = ssh://<username>@<server 2 ip>/opt/git/foo.git
By default git will push all branches to the remotes but we can have it push the current branch only.
git config --global push.default current
Git hooks can help automate your deployment process. Checkout the list of client and server-side Git hooks available.