Skip to content

Instantly share code, notes, and snippets.

@rcline
Last active March 7, 2019 19:38
Show Gist options
  • Save rcline/e010918635d8359a2c1aa83135087797 to your computer and use it in GitHub Desktop.
Save rcline/e010918635d8359a2c1aa83135087797 to your computer and use it in GitHub Desktop.
pre-push hook to protect upstream/master
#!/bin/bash
# @link https://gist.github.com/rcline/e010918635d8359a2c1aa83135087797
#
# A hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# Steps to install, from the root directory of your repo...
# 1. Copy the file into your repo at `.git/hooks/pre-push`
# 2. Set executable permissions, run `chmod +x .git/hooks/pre-push`
#
# Try a push to master, you should get a message `*** [Policy] Never push code directly to...`
#
# For examples:
# - protected branch is master
# - feature branch is test
# - remote containing protected branch is upstream
# - forked remote user
#
# Example failing commands:
# - `git push` # when `master` is the current branch and is configured with an upstream of `upstream/master`
# - `git push upstream master` # from any currently checkedout branch
#
# Example passing commands:
# - `git push` # when any branch but `master` is the current branch
# - `git push user` # when any branch but `master` is the current branch
# - `git push user master`
# - `git push user test`
# - `git push upstream test`
origin="$1"
remoteUrl="$2"
# current branch can be different then the branch being pushed up
# currentBranch=`git rev-parse --abbrev-ref HEAD`
# if we need to look at the specific push command arguments or flags parse this
# pushCommand=`ps -ocommand= -p $PPID`
# An empty SHA
# z40=0000000000000000000000000000000000000000
# our protected trunk branch
protectedBranch="master"
# our designated upstream remote org
githubOrgName="web-platform"
# Identified destructive operations
# isDestructive='force|delete|\-f|"+master"'
while read local_ref local_sha remote_ref remote_sha
do
# if "$local_sha" = $z40 this is an attempt to delete the remote branch
# if "$remote_sha" = $z40 this branch has not yet been pushed to the remote
# else range="$remote_sha..$local_sha" is the range of the updates being pushed to the remote branch
localSha="$local_sha"
remoteSha="$remote_sha"
localBranch=$(sed -e 's,.*/\(.*\),\1,' <<< "$local_ref")
remoteBranch=$(sed -e 's,.*/\(.*\),\1,' <<< "$remote_ref")
done
if [[ "$localBranch" == "$protectedBranch" && "$remoteUrl" == *"$githubOrgName/"* ]]; then
echo
echo "Prevented push to $protectedBranch."
echo "You are trying to push directly to our trunk protected branch, this is not allowed for your own safety."
echo "If you really want to do this, see docs about the --no-verify flag."
echo
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment