Our Git Deployment Setup

This article will explain our git deployment process using bears and reapers. Our setup assumes that you want separate development and production environments on a webserver in addition to the local repositories for each person on your team.

Git Goin’

The first step is to install git on the server as well as locally, which I will not get into as this has been explained many times before. The first thing to understand is that the development site and the production site will each have 2 repositories. The real home of each site resides in its associated bare repository which lies *outside* the public web root (typically named public_html or httpdocs). A bare repository does not have any actual working files that you can see, just a bunch of compressed git guts. So, create a new directory alongside public_html. You can create a bare repo using git init –bare from your shell on the server. If you are having permissions problems at this point, you can also create two directories within public_html, one for the site and one for the bare repo. You will then need to point the virtual directory for the site to the new site directory within public_html via apache or plesk. I’ve represented the bare repo in the graphic above with a bear.

Connect the dev site to the bear

Next you will want to initialize git in the public web root where the dev site will reside using a standard git init. This is in the same directory where all the working files for the site will reside. You’ll want to add a .htaccess in the .git directory you just created so that nobody can dig through your repo. Simply create webroot/.git/.htaccess and add ‘deny from all’, assuming you are using apache. Now this working repo needs to be able to pull from the bare repo, so type git remote add origin /var/www/path/to/devsite/barerepo.git/, replacing the path to the bare repo as needed. I’ve represented the regular dev site repo using the grim reaper and the working file tree with a tree.

Strength of a Bear

The strength of a bear

At this point you can create a local standard git repository and build your site using whatever software you like. Be sure to add any temporary files or config files to your gitignore. Also run this command to create a blank .gitignore in any empty directories you may want(since git doesnt track empty directories): find . -type d -empty -exec touch {}/.gitignore \;. Note that you and others on you team will want to use the same username on the webserver when adding your remote. This prevents permissions problems on the server, and yet the git log will maintain your names based on how you installed git locally. Add the bare repo as your remote using a regular git remote add origin ssh://username@domain.com/var/www/path/to/barerepo.git/. You can now push to the bare repo. Now if you wanted, you could pull from the bare repo into the working directory of the dev site. After you make sure that works, try using an update hook under barerepo.git/hooks/post-update that looks something like this:


echo “*** Attempting to update Dev Site ***”
echo cd /var/www/path/to/site || exit
unset GIT_DIR
git pull origin master# You could compile sass stylesheets here if thats yer thing

echo “*** If there are no errors above, the dev site has been updated ***”

exec git-update-server-info

Putting it all together

Make sure that post-update hook is executable by running chmod +x barerepo.git/hooks/post-update. If the post-update file is not executable the hook will very quietly do nothing. Once you get this working, you can pretty much do the exact same thing for the production server except that your local remote will look like this: git remote add production ssh://username@domain.com/var/www/path/to/production/barerepo.git. The only other difference is that the path in the remotes and hook must refer to the production path. Now when you want to push to production, all you do is get a fresh pull from the dev remote with ‘git pull origin master’ and then push to production with git push production master. This helps to prevent accidentally pushing to production since you actually have to type ‘production’. Your teammates can do this too and there shouldn’t be any permissions problems. You can also build a staging server using this same pattern if needbe.

What about the database and user uploaded files?

Of course you will want to keep the database and user uploaded files outside of git, so you’ll need a separate method of pushing this stuff around. We frequently use a CMS called Concrete5 which saves these user uploaded files and has a database. I’ve developed the script below which will put both the source and target sites into maintenance mode briefly, transfer the database and the files directory. It’ll run tests and keep backups, but you should be extremely careful when entering the database connection information and files directories. You can use it to transfer to production or back to development. You may be able to adapt this script to your needs if you aren’t using Concrete5.

Concrete5 database and file migration script