I’ve been trying to get my head around a simple git based workflow for deploying from development to staging to live server environments. I found this post extremely useful in achieving a basic development -> live workflow, but adding in a staging step is very useful if you want to let clients preview work before pushing the changes to their live websites. So I’ve devised the following workflow as a means of achieving this goal.

Firstly, I’d suggest reading the post mentioned above, as this explains where I’m coming from with my 3 step approach.


I have 2 branches in my local repository, one for staging and another for live.

FYI, to create a new branch in your local repository and switch to it use:

git checkout -b branchname

I also have a remote setup called ‘web’ which links to my remote private repository (this should already be setup if you’ve followed the approach on toroid.org mentioned at the start of this article, but for reference:

git remote add web ssh://root@

I have a post-receive hook in my remote repository which I have defined to look at the refname stdin. The post-receive hook doesn’t accept any arguments, but you can use stdin arguments, as explained here. If I’m pushing the staging branch I deploy to the staging document root, if I push the live branch I deploy to the live document root. So my post-receive hook now looks like this:


read oldrev newrev refname
echo “Old revision: $oldrev”
echo “New revision: $newrev”
echo “Reference name: $refname”

if [ “$refname” = “refs/heads/staging” ]
GIT_WORK_TREE=/home/staging/public_html git checkout -f staging

echo “Resetting file ownership for staging site”;
chown user1:group1 -R /home/staging/public_html
chown user1:nobody /home/staging/public_html

if [ “$refname” = “refs/heads/live” ]
echo “Checking out to live document root”
GIT_WORK_TREE=/home/live/public_html git checkout -f live

echo “Resetting file ownership for live site”;
chown user1:group1 -R /home/live/public_html
chown user1:nobody /home/live/public_html

So the update workflow goes like this:

1. Checkout the staging branch on your local repository:

git checkout staging

2. Make any changes you want to make on your local development version.

3. Add the changes to the repository to your local staging branch.

git add .

4. Commit those changes to the local staging branch

git commit -m”Staging changes”

5. Push those changes to the web staging branch

git push web staging

6. This will now also deploy those changes to the staging document root by checking out the staging branch to your staging document root.

Check you’re happy with the changes on staging. Assuming everything looks peachy you can now deploy to the live document root. To do this do the following:

1. Checkout and switch to the live branch locally

git checkout live

2. Merge your staging branch with your live branch

git merge staging live

3. Push your live branch up to your remote

git push web live

This will now also deploy the changes to your live document root as with the staging step explained above.

So I hope that’s some help to someone struggling with achieving something similar. There are probably 101 better ways of achieving this that someone more familiar with git might use, but I think this does what I need for now atleast. Comments, suggestions, improvements very welcome.