Deploying your site with Git

I have been using Git quite a bit lately, from my work on the CodePlex team, along with several personal projects. Git is pretty powerful, and given its distributed nature, it has some pretty cool capabilities one of them is to push source code from one location to another - “developer ftp”. When I was creating my updated blog, I really wanted to find a nice way to use Git to push changes to my site onto the production web server.

Since I am using Pretzel to generate a static version of this site on my desktop, I just needed the ability to moving the contents of the output folder (_site) onto the my public web server hosted at Bluehost. This would work the same way if I was using Jekyll or any other static site generator. I could FTP the files between machines, but I liked the idea of having another remote location that had a versioned copy of my site. Additionally, if something went wrong, since the site was stored with Git, I could always revert to a previous working version.

The flow goes like this:

  • Make a change to blog source or create a blog post
  • Pretzel Bake or Jekyll –server
  • Commit the changes within the _site folder
  • Git Push to Remote setup within Bluehost
  • Within Remote, post-commit trigger does a pull into the www root

With this flow, only changed items are transfered, and git handles the compression and decompression on either end.

####Configuring Git on bluehost#### Getting Git running on bluehost is pretty simple, I doubt that bluehost really supports this scenario but hey it works. For me this is just a small repository that handles my blog, large source repositories go on CodePlex. First you need to request SSH access from bluehost, go to the bluehost dashboard and select Manage SSH Access. Once you have SSH access use something like Putty to SSH into your account.

  1. Create source directory to store git tarball
    
    myuser@markgroves.us [~/]# mkdir src
    myuser@markgroves.us [~/]# cd src
    
  2. Download latest source
    
    myuser@markgroves.us [~/src]# wget http://git-core.googlecode.com/files/git-1.7.11.rc2.tar.gz
    myuser@markgroves.us [~/src]# tar xvfz git-1.7.11.rc2.tar.gz
    
  3. Build Git
    
    myuser@markgroves.us [~/src]# cd git-1.7.11.rc2
    myuser@markgroves.us [~/src/git-1.7.11.rc2]# ./configure --prefix=$HOME
    myuser@markgroves.us [~/src/git-1.7.11.rc2]# make SHELL="/bin/bash" install
    
  4. Setup Git Remote to store site
    
    myuser@markgroves.us [~]# export PATH=$PATH:$HOME/bin
    myuser@markgroves.us [~]# mkdir -p ~/git/yoursitename.git
    myuser@markgroves.us [~]# cd ~/git/yoursitename.git
    myuser@markgroves.us [~/git/yoursitename.git]# git --bare init
    

Now you have a bare git repository setup on bluehost. But a bare git repository won’t do much, we need a expanded working directory within the www root. Since we are going to Git Push to the bare repository we will setup a post-receive hook to do a pull into the working directory.

  1. Setup working directory
    
    myuser@markgroves.us [~]# cd www/
    myuser@markgroves.us [~/www]# git clone ~/git/yoursitename.git/ .
    
  2. Setup the post receive hook

    Create a file named post-receive and place it in ~/git/yoursitename.git/hooks the contents should look like:

    
    GIT\_REPO=$HOME/git/yoursitename.git
    TMP\_GIT\_CLONE=$HOME/tmp/yoursitename
    PUBLIC\_WWW=$HOME/www
    \#!/bin/bash
    cd $PUBLIC\_WWW || exit
    unset GIT\_DIR
    git pull
    exec git-update-server-info
    exit
    

    The first three lines are just setting up a few default folders parameters. Then we are going to change into the www directory and to a pull. The unset GIT_DIR is necessary since there is a default setting that won’t respect the directory while you are in the bare git repository. The exec git-update-server-info command resets the defaults.

    Make sure you set the post-receive hook file to be executable: chmod +x post-receive

So now each time you do a git push into the bare repository, the post-receive hook fires and does a pull into the www folder, updating the site.

####Setup your local repository#### Both Pretzel and Jekyll, by default, are configured to output the “compiled” site into a _site folder. This folder contains a complete folder structure that will working within your www folder on your web server. Since this is the folder that I want to push to bluehost I needed to do a little git trickery to not push the parent folders.

  1. Add _site to the git ignore list
    
    \#site build output
    \_site/
    

    create a .gitignore file within your base site folder, this assumes you have your site within git for development

  2. Git initiate the _site folder to setup a new git repository
    
    D:\development\markgroves.us\\\_site>  git init
    D:\development\markgroves.us\\\_site [master]> git add .
    D:\development\markgroves.us\\\_site [master]> git commit -m 'initial commit of site'
    
  3. Setup the remote to the bluehost remote git repository
    
    D:\development\markgroves.us\\\_site [master]> git remote add deploy myuser@mysitename:~/git/mysitename.git
    
  4. Deploy changes to the server
    
    D:\development\markgroves.us\\\_site [master]> git push deploy master
    

####Conclusion#### Now each time I do a git push the remote bare repository will get updated, and the post-receive hook will fire updating the www folder and the site. For me this is great, keep everything versioned using git, and with just one additional commant (git push) I get the my site updated in seconds.