Skip to content

Instantly share code, notes, and snippets.

@joshbeitelspacher
Created March 14, 2011 05:06
Show Gist options
  • Save joshbeitelspacher/868803 to your computer and use it in GitHub Desktop.
Save joshbeitelspacher/868803 to your computer and use it in GitHub Desktop.
A Git post-receive hook for deploying files from a branch to a configurable location after every push.
#!/bin/bash
#
# A Git post-receive hook to deploy content from a Git repository on every
# push into a repository. The branches that should be automatically deployed
# must be listed in the config file of the Git repository. The simplest possible
# configuration is shown below:
#
# [deploy "refs/heads/master"]
# directory = /var/www/site
#
# Whenever the content of refs/heads/master is changed the new contents will
# be extracted to a temporary directory, /var/www/site will be moved into
# another temporary directory, the first temporary directory will be moved to
# /var/www/site, and finally the second temporary directory will be deleted.
# If the temporary directories are on the same filesystem as the destination
# directory then the destination directory will only be inaccessible for a
# very brief time because the directories moves will only require renames.
# However, this is still not an atomic operation. The directory will be
# removed and then immediately replaced with a new directory with updated
# contents, but it is possible another process could attempt to read a file
# between the two operations and receive a file not found error.
#
# In order to ensure the temporary directories are on the local filesystem a
# temp option can be added to the configuration:
#
# [deploy "refs/heads/master"]
# directory = /var/www/site
# temp = /var/temp/master-XXX
#
# When temp is set the temporary directories will be created using the given
# mktemp template (see "man mktemp" for more information). This setting is
# especially important if the default temporary directory is on a tempfs
# filesystem.
#
# In order to move the /var/www/site directory the user that pushes into
# the repository must have write access to /var/www. If this is not the case
# then moveContents = true should be added to the configuration. When
# moveContents is set to true the contents of the /var/www/site directory will
# be moved instead of the directory itself. Because more move operations will
# be needed, this will result in more intermediate states.
#
while read oldrev newrev refname
do
directory=$(git config deploy.${refname}.directory)
if [ "${directory}" ]; then
staging=$(mktemp -d $(git config deploy.${refname}.temp))
mkdir ${staging}/new
git archive ${newrev} | (cd ${staging}/new && tar xf -)
moveContents=$(git config --bool deploy.${refname}.moveContents)
if [ "${moveContents}" == "true" ]; then
shopt -s dotglob
mkdir ${staging}/old
mv ${directory}/* ${staging}/old
mv ${staging}/new/* ${directory}
else
mv ${directory} ${staging}/old
mv ${staging}/new ${directory}
fi
rm -rf ${staging}
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment