Skip to content

Instantly share code, notes, and snippets.

@stefansundin
Last active October 12, 2023 10:33
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save stefansundin/d465f1e331fc5c632088 to your computer and use it in GitHub Desktop.
Save stefansundin/d465f1e331fc5c632088 to your computer and use it in GitHub Desktop.
Git pre-push hook to prevent force pushing the master/main branch.
#!/bin/bash
# This script will install a Git pre-push hook that prevents force pushing the master/main branch.
# There are three variants that I have built:
# - pre-push: prevents force-pushing to master/main.
# - pre-push-2: prevents force-pushing to master/main depending on the remote (you need to edit the file!).
# - pre-push-3: prevents any type of pushing to master/main.
# Set the desired version like this before proceeding:
# FILE=pre-push
# Single repo installation:
# curl -fL https://gist.githubusercontent.com/stefansundin/d465f1e331fc5c632088/raw/install-pre-push.sh | sh -s ${FILE:-pre-push}
# Uninstall:
# rm .git/hooks/pre-push
# Global installation instructions:
# mkdir $HOME/.githooks
# git config --global core.hooksPath $HOME/.githooks
# curl -fL -o $HOME/.githooks/pre-push https://gist.githubusercontent.com/stefansundin/d465f1e331fc5c632088/raw/${FILE:-pre-push}
# chmod +x $HOME/.githooks/pre-push
# Uninstall:
# rm $HOME/.githooks/pre-push
GIT_DIR=`git rev-parse --git-common-dir 2> /dev/null`
echo
echo
if [ "$GIT_DIR" == "" ]; then
echo This does not appear to be a git repo.
exit 1
fi
if [ -f "$GIT_DIR/hooks/pre-push" ]; then
echo There is already a pre-push hook installed. Delete it first.
echo
echo " rm '$GIT_DIR/hooks/pre-push'"
echo
exit 2
fi
FILE=${1:-pre-push}
echo "Downloading $FILE hook from https://gist.github.com/stefansundin/d465f1e331fc5c632088"
echo
curl -fL -o "$GIT_DIR/hooks/pre-push" "https://gist.githubusercontent.com/stefansundin/d465f1e331fc5c632088/raw/$FILE"
if [ ! -f "$GIT_DIR/hooks/pre-push" ]; then
echo Error downloading pre-push script!
exit 3
fi
chmod +x "$GIT_DIR/hooks/pre-push"
echo "You're all set!"
echo "P.S. There is now a way to install this globally, see the instructions on the gist page."
exit 0
#!/bin/bash
# Prevents force-pushing to master/main.
# Install:
# cd path/to/git/repo
# curl -fL -o .git/hooks/pre-push https://gist.githubusercontent.com/stefansundin/d465f1e331fc5c632088/raw/pre-push
# chmod +x .git/hooks/pre-push
BRANCH=`git rev-parse --abbrev-ref HEAD`
PUSH_COMMAND=`ps -ocommand= -p $PPID`
if [[ "$BRANCH" =~ ^(master|main)$ && "$PUSH_COMMAND" =~ force|delete|-f ]]; then
echo
echo "Prevented force-push to $BRANCH. This is a very dangerous command."
echo "If you really want to do this, use --no-verify to bypass this pre-push hook."
echo
exit 1
fi
exit 0
#!/bin/bash
# Use this file to prevent force pushes only to specific remotes (e.g. work).
# You have to customize it below ("workorg/").
# Prevents force-pushing to master.
# Install:
# cd path/to/git/repo
# curl -fL -o .git/hooks/pre-push https://gist.githubusercontent.com/stefansundin/d465f1e331fc5c632088/raw/pre-push-2
# chmod +x .git/hooks/pre-push
ORIGIN="$1"
REMOTE_URL="$2"
BRANCH=`git rev-parse --abbrev-ref HEAD`
PUSH_COMMAND=`ps -ocommand= -p $PPID`
if [[ "$BRANCH" =~ ^(master|main)$ && "$PUSH_COMMAND" =~ force|delete|-f && "$REMOTE_URL" == *"workorg/"* ]]; then
echo
echo "Prevented force-push to $BRANCH. This is a very dangerous command."
echo "If you really want to do this, use --no-verify to bypass this pre-push hook."
echo
exit 1
fi
exit 0
#!/bin/bash
# Prevents any type of pushing to master/main.
# Install:
# cd path/to/git/repo
# curl -fL -o .git/hooks/pre-push https://gist.githubusercontent.com/stefansundin/d465f1e331fc5c632088/raw/pre-push
# chmod +x .git/hooks/pre-push
BRANCH=`git rev-parse --abbrev-ref HEAD`
if [[ "$BRANCH" =~ ^(master|main)$ ]]; then
echo
echo "Prevented push to $BRANCH."
echo "If you really want to do this, use --no-verify to bypass this pre-push hook."
echo
exit 1
fi
exit 0
@stefansundin
Copy link
Author

@bilogic You probably want a pre-receive hook if you have control over the server. I don't have a script ready for you so you are on your own. 😆

It would really have accelerated things if you posted more information up-front, but I guess we finally arrived at the solution. 😅

Good luck!

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