Netskin Logo

How to Prevent force-push to master

#git
by Michael Blum on 04.10.2022

Preamble

We all know there are certain things in git, that you should not do. For example you should never force push to the master branch! (For real, do not do this!) Force pushing on your own feature branch is fine though. While it depends on your personal style, I do not like to have 100 “wip” commits when developing a bigger feature.

Now imagine this: You want to force push something to your personal feature branch. After you amended a little fix to your last commit (with git commit --amend) you send the force push to your branch but then you realize… oh… That was not my feature branch I am on. That was master (release, main or any other important branch)! While it is not that terrible and unfixable, you will spend the next minutes informing your team, that the branch is currently in a “dirty” state and that you need to do some rebasing to fix this.

The Fix

To prevent such accidents I found a neat little helper that doesn’t let you force push to any important branches that you might have. I wanted it to be a global fix, so it automatically works on all your git projects.

# create a global git-hook dir
mkdir ~/git
mkdir ~/git/hooks

# tell git about your new global hook space
git config --global core.hooksPath ~/git/hooks/

# create an awesome hook - the filename is important here!
touch ~/git/hooks/pre-push

# Make it executable
chmod +x ~/git/hooks/pre-push

Now fill ~/git/hooks/pre-push with this little script. Use the variable PROTECTED_BRANCHES to add any other important branch, that you want to protect.

#!/bin/bash
# Prevents force-pushing to master

BRANCH=`git rev-parse --abbrev-ref HEAD`
PUSH_COMMAND=`ps -ocommand= -p $PPID`
PROTECTED_BRANCHES="^(master|release*)"
FORCE_PUSH="force|delete|-f"

if [[ "$BRANCH" =~ $PROTECTED_BRANCHES && "$PUSH_COMMAND" =~ $FORCE_PUSH ]]; then
  echo "Prevented force-push to protected branch \"$BRANCH\" by pre-push hook"
  exit 1
fi
exit 0

Coloured Bash

Here is another quite helpful thing when dealing with git directly on your bash, instead if just using a GUI: By putting the following snippet to your .bashrc-file, you get a nice color scheme with green hostname, blue pathname and yellow git branchname. This should work on all Linux or Unix operating systems.

parse_git_branch() {
  git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
PS1="${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[01;33m\]\$(parse_git_branch)\[\033[00m\]$ "

Test

Instead of pushing to the branch it should display an error message like this:

git push --force
Prevented force-push to protected branch "release" by pre-push hook
error: failed to push some refs to 'git@gitlab.netskin.com:netskin/my-awesome-project.git'

Please remember to not to test this on any important project you are working on. ;)

Some more hints how to deal with the force are linked below. Happy Coding!

Resources

❮ Moving from Postgresql to SQL Server
Using UNION Queries with Rails ❯
Netskin Logo