Deploying with Git

I’ve been spending the day putting together a more automated method of deploying my websites – deploying with Git after I push to the remote repository on the server. Not only is this incredible easy to deploy changes once setup, it ensures that my live site is tied in nicely with my version control. Anyway it took a little time to tinker with so I thought I’d share my method I’m using. This approach uses a script to build an bare repository on the server, and hooks to pull changes to the live site. As every production environment is different I suggest this as a guide and make appropriate changes to suite your environment.

Setting up the server

So, I’m going to talk through two bash scripts – createproject, and removeproject. When I want to start working on a new project, I’ll run createproject which will setup the repositories and create the update hook files to ensure push deployment. If I wish to remove a project, removeproject will remove files and directories keeping things tidy.

createproject

This bash script I execute when I want to create a new project. So, as this is a script, let’s start with a “shebang”. This will tell the shell which interpreter to run the script.

#!/bin/sh

My script relies upon a project name being passed so I check that an argument is present. Without a project name, this will be passed as blank which will yield unwanted results.

if [ $# -eq 0 ]
then
echo "No arguments supplied"
exit 0
fi

The name variable is our project name which will be used to name the repository base folders.

name=$1

This will setup my bare repository that I will push from my local repository.

sudo mkdir -p /var/git/$name.git && cd /var/git/$name.git
sudo git init --bare

With my bare repository in place, next step is to clone the new repository. This will, at this stage, be an empty repository but it will set our remote url and set everything up so we can pull any changes automatically when we push changes to the project.

cd /var/www/
sudo git clone /var/git/$name.git $name

Next, I include a post-update hook so that every time I push changes to the bare repository it will pull those changes to the live repository.

sudo tee /var/git/$name.git/hooks/post-update <<EOF >/dev/null
#!/bin/sh

echo
echo "**** Pulling changes into Live [Origin's post-update hook]"
echo

cd /var/www/$name || exit
unset GIT_DIR
git pull origin master

exec git-update-server-info
EOF

One thing to beware is how you set up permissions when you authenticate while pushing changes. If you only have one user and that user is the same on your local machine as on the server, then things are much easier. Just make sure your bare repository and live folders have their permissions and ownership set accordingly. I opted for allowing group access through my developer group “dev” in which case ensure each user is a member of that group. Depending on your own security policy setting permissions is something you may need to include in the script to automate the process.

So, now I have a script that can handle creating new projects.When I want to create a new project I run this line

./createproject myproject
removeproject

In the process of writing this script I found myself creating projects, finding a bug, making changes, removing the project and starting over again and again. So I wrote another script that I think will continue to be useful which simply removes a project. Thankfully Git repositories and self contained within their folders so I just remove the two folders I created:

Again, a shebang as this is a script

#!/bin/bash

Again, I need to know what project name so I know which folder to delete (otherwise I may end up deleting the entire /var/www folder)

if [ $# -eq 0 ]
then
echo "No arguments supplied"
exit 0
fi

name=$1

And delete the two folders containing both repositories.

sudo rm -rf /var/git/$name.git
sudo rm -rf /var/www/$name

So, when I need to remove a project I can do this:

./removeproject myproject

Setting up the local repository

So, for my local repository I just need to add a remote URL to allow me to push. Here I’m using SSH. As I’m working on my local network I run the following:

git remote add origin martyn@192.168.0.100;/var/git/myproject.git

So now every time I git push origin master after a commit my changes are automatically pulled to the live site.