Skip to content

Instantly share code, notes, and snippets.

@xkr47
Last active December 20, 2015 10:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xkr47/10004875 to your computer and use it in GitHub Desktop.
Save xkr47/10004875 to your computer and use it in GitHub Desktop.
How to validate the files being pushed to a remote Git repository and leave repository untouched if validation failed - works with bare and non-bare repos
#!/bin/bash
# This file should be installed in the remote repository as:
# - <path-to-bare-repo.git>/hooks/update if you have a bare repository
# - <path-to-regular-repo>/.git/hooks/update if you have a regular repository
set -e
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "${refname}" -o -z "${oldrev}" -o -z "${newrev}" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# In this example we only want to validate the master branch; if not, just exit if pushed branch is not master
if [ "${refname}" != "refs/heads/master" ]; then
exit 0
fi
# In this example we want to forbid deleting the master branch
zero="0000000000000000000000000000000000000000"
if [ "${newrev}" = "$zero" ]; then
echo "Deletion of master branch is not supported"
exit 1
fi
# convert to absolute path
export GIT_DIR="$(cd "$GIT_DIR" ; pwd)"
# check permissions
if [ ! -w $GIT_DIR/index ]; then echo "Permission denied - check file permissions in $GIT_DIR" ; exit 1 ; fi
# use separate index file and temporary checkout location when validating (for compatibility with non-bare repository - see https://gist.github.com/xkr47/8348709)
export GIT_INDEX_FILE="$GIT_DIR/hook-update-index"
export TMP_CHECKOUT="${GIT_INDEX_FILE}_dir/"
# make sure we clean up regardless of outcome
cleanup () {
set +e
rm -f "$GIT_INDEX_FILE"
rm -rf "$TMP_CHECKOUT"
}
trap cleanup EXIT
# checkout pushed revision to temporary directory and cd to that directory
git read-tree "${newrev}"
git checkout-index --prefix="${TMP_CHECKOUT}" -a
cd "${TMP_CHECKOUT}"
#########################################################################
#########################################################################
#
# Do the pre-push validation below - use "exit 1" to reject
#
#########################################################################
#########################################################################
# example: make sure we always have LICENSE.txt in the root of the project
if [ ! -e LICENSE.txt ]; then
echo LICENSE.txt missing
exit 1
fi
@xkr47
Copy link
Author

xkr47 commented Dec 20, 2015

See https://gist.github.com/xkr47/8348709 for how to set up non-bare remote repository, useful together with this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment