Search code examples
gitwebgit-post-receivewebsite-deployment

Git for Websites / post-receive / Separation of Test and Production Sites


I'm using Git to manage my website's source code and deployment, and currently have the test and live sites running on the same box. Following this resource http://toroid.org/ams/git-website-howto originally, I came up with the following post-receive hook script to differentiate between pushes to my live site and pushes to my test site:

while read ref
do
  #echo "Ref updated:"
  #echo $ref -- would print something like example at top of file
  result=`echo $ref | gawk -F' ' '{ print $3 }'`
  if [ $result != "" ]; then
    echo "Branch found: "
    echo $result
    case $result in
      refs/heads/master )
        git --work-tree=c:/temp/BLAH checkout -f master
        echo "Updated master"
        ;;
      refs/heads/testbranch )
        git --work-tree=c:/temp/BLAH2 checkout -f testbranch
        echo "Updated testbranch"
        ;;
      * )
        echo "No update known for $result"
        ;;
    esac
  fi
done
echo "Post-receive updates complete"

However, I have doubts that this is actually safe :) I'm by no means a Git expert, but I am guessing that Git probably keeps track of the current checked-out branch head, and this approach probably has the potential to confuse it to no end.

So a few questions:

  1. IS this safe?

  2. Would a better approach be to have my base repository be the test site repository (with corresponding working directory), and then have that repository push changes to a new live site repository, which has a corresponding working directory to the live site base? This would also allow me to move the production to a different server and keep the deployment chain intact.

  3. Is there something I'm missing? Is there a different, clean way to differentiate between test and production deployments when using Git for managing websites?

As an additional note in light of Vi's answer, is there a good way to do this that would handle deletions without mucking with the file system much?

Thank you, -Walt

PS - The script I came up with for the multiple repos (and am using unless I hear better) is as follows:

sitename=`basename \`pwd\``

while read ref
do
  #echo "Ref updated:"
  #echo $ref -- would print something like example at top of file
  result=`echo $ref | gawk -F' ' '{ print $3 }'`
  if [ $result != "" ]; then
    echo "Branch found: "
    echo $result
    case $result in
      refs/heads/master )
        git checkout -q -f master
        if [ $? -eq 0 ]; then
            echo "Test Site checked out properly"
        else
            echo "Failed to checkout test site!"
        fi
        ;;
      refs/heads/live-site )
        git push -q ../Live/$sitename live-site:master
        if [ $? -eq 0 ]; then
            echo "Live Site received updates properly"
        else
            echo "Failed to push updates to Live Site"
        fi
        ;;
      * )
        echo "No update known for $result"
        ;;
    esac
  fi
done
echo "Post-receive updates complete"

And then the repo in ../Live/$sitename (these are "bare" repos with working trees added after init) has the basic post-receive:

git checkout -f
if [ $? -eq 0 ]; then
    echo "Live site `basename \`pwd\`` checked out successfully"
else
    echo "Live site failed to checkout"
fi

Solution

  • Would a better approach be to have my base repository be the test site repository (with corresponding working directory), and then have that repository push changes to a new live site repository, which has a corresponding working directory to the live site base? This would also allow me to move the production to a different server and keep the deployment chain intact.

    Yes definitely. It's a very rare occasion you want your test site hosted right next to your production site. It's dangerous and unprofessional in almost every regard, not to speak about database corruption, webserver lockups etc.

    I do usually have a VM setup for testing purposes. Works very well and I can have it with me on my laptop while travelling.

    Using git to deploy your website is a very good idea, there are a lot of other people doing so (e.g. Rob Conery). If you happen to have a live and testing site anyway, you should have seperate branches for them in your repository, set-up as remote-tracking branches on the corresponding server repositories. Your workflow becomes as easy as doing work in your test branch, push it to test, test it, merge to live and push live.

    Honestly, don't make it too hard for yourself.