Git has this great feature whereby you can execute arbitrary scripts whenever something happens on your git repository. A common use case for this is a pre-receive hook on the remote repository which prevents people with access from doing destructive actions, like force pushing, which are incredibly easy to do by accident.

Many projects use GitHub as their remote repository, and as GitHub is a service, they do not permit you to upload arbitrary scripts to run on their servers. Makes sense, but how then can you protect your codebase?

Turns out, from version 1.8.2, Git has a new pre-push hook that lets you do the same thing on your local repository. It's not as handy as setting it up on the remote for all your users, but it does allow you the developer to protect yourself from... yourself.

Setup the hook

For any repository you want to protect, you need to create a new file called pre-push in the .git/hooks directory and make sure the file has permission to be executed. Inside the file, you'll add the script you want to run, here's the one I use:

#!/bin/bash protected_branch='master' current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,') if [ $protected_branch = $current_branch ] then read -p "You're about to push master, is that what you intended? [y|n] " -n 1 -r < /dev/tty echo if echo $REPLY | grep -E '^[Yy]$' > /dev/null then exit 0 # push will execute fi exit 1 # push will not execute else exit 0 # push will execute fi

This checks if the current branch is master , and if so it will prompt you to confirm what you're doing. It doesn't detect whether you're doing a normal push, or a force push, as I prefer to have the confirmation on any push to master. This script is borrowed heavily from scripts by pixelhandler and Itty Bitty Labs. For anyone wondering, the weird use of grep is so that this works on Windows as well as *nix systems.

Once you've added this script to your .git/hooks/pre-push file, any push command which operates on the master branch will require confirmation. Simple, but very effective.