Skip to content

Instantly share code, notes, and snippets.

@ColCh
Last active September 26, 2024 08:12
Show Gist options
  • Save ColCh/9d48693276aac50cac37a9fce23f9bda to your computer and use it in GitHub Desktop.
Save ColCh/9d48693276aac50cac37a9fce23f9bda to your computer and use it in GitHub Desktop.
Git pre-push hook to confirm pushing to master

Git pre-push hook

It will check if current branch is master, then ask a confirmation, in case of master branch

Articles with initial info: https://dev.ghost.org/prevent-master-push/, https://coderwall.com/p/jp7d5q/create-a-global-git-commit-hook

Demo

http://imgur.com/a/EXGAW

To install

  1. Enable git templates
git config --global init.templatedir '~/.git-templates'

  1. Create a directory to hold the global hooks:
mkdir -p ~/.git-templates/hooks
  1. Write your hook in ~/.git-templates/hooks

See file pre-push in this gist.

Copy it to ~/.git-templates/hooks/pre-push

  1. Make it executable
chmod a+x ~/.git-templates/hooks/pre-push
  1. In currently existing project, do reinit

git init

This will not overwrite existing commits, or existing hooks.

Done!

#!/bin/bash
protected_branch='master'
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [ $protected_branch = $current_branch ]
then
echo -en "\033[31mYou're about to push master, is that what you intended? [y|n] \033[0m"
echo -en "\033[1m"
read -n 1 -r < /dev/tty
echo -en "\033[0m"
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
@mosra
Copy link

mosra commented Feb 16, 2020

Important security note -- the above will give you a false sense of security and won't work for things like

git push -f origin e09b7418a310114f6aaf495f969c3859095a99af:master

Which was, in my case, the main cause of why I pushed to master by accident. Fixed version of the script is below and also in my fork:

#!/bin/bash

protected_branch='master'

if read local_ref local_sha remote_ref remote_sha; then
    if [[ "$remote_ref" == *"$protected_branch"* ]]; then
        echo -en "\033[1;33mYou're about to push to master, is that what you intended? [y|n] \033[0m"
        echo -en "\033[1m"
        read -n 1 -r < /dev/tty
        echo -en "\033[0m"

        echo
        if echo $REPLY | grep -E '^[Yy]$' > /dev/null; then
            exit 0 # push will execute
        fi
        exit 1 # push will not execute
    fi
fi

(Note you'll need to rm .git/hooks/pre-push && git init to make the repos pick the updated version.)

In any case, thanks for this -- it got me 50% of the way at least :)

@ColCh
Copy link
Author

ColCh commented Feb 17, 2020

Wow thank you for fixing this issue! That was very unclear for me until this moment :)

@sloev
Copy link

sloev commented Jul 5, 2021

@mosra i have written a complete setup instruction (for mac) in this fork:
https://gist.github.com/sloev/9064296899ef8cd12d3061e569ee7064

content:

Git pre-push hook

It will check if current branch is master, then ask a confirmation, in case of master branch

install

  1. install a recent version of git (https://git-scm.com/download/mac)
    eg:
    $ brew install git
    $ echo 'alias git="/us/bin/local"' >> ~/.zshrc
  2. create global git hooks directory
    $ mkdir ~/.githooks
  3. save the pre-push script beneith in ~/.githooks/pre-push
  4. make it executable: chmod +x ~/.githooks/pre-push
  5. tell git how to find it:
    $ git config --global core.hooksPath /Users/Someone/.githooks/

example:

$ foo@somewhere something  > git push
You're about to push to master, is that what you intended? [y|n] n
error: failed to push some refs to 'github.com:someone/something.git'
$ foo@somewhere something  >

@shivanshBTW
Copy link

I added a few messages to indicate the status better, can someone help out with making the protected_branch an array and checking if we are pushing into any one of them

#!/bin/bash

protected_branch='main'

if read local_ref local_sha remote_ref remote_sha; then
	if [[ "$remote_ref" == *"$protected_branch"* ]]; then
		echo -en "\033[1;33mYou're about to push to $protected_branch, is that what you intended? [y|n] \033[0m"
		echo -en "\033[1m"
		read -n 1 -r </dev/tty
		echo -en "\033[0m"

		echo
		if echo $REPLY | grep -E '^[Yy]$' >/dev/null; then
			echo -en "\033[1;33mPushing To $protected_branch\033[0m"
			echo -en "\033[1m"
			exit 0 # push will execute
		fi
		echo -en "\033[1;33mCancelled push to $protected_branch\033[0m"
		echo -en "\033[1m\n"
		exit 1 # push will not execute
	fi
fi

@mosra
Copy link

mosra commented Sep 26, 2024

It's on my fork, not really an array but should be sufficient nevertheless: https://gist.github.com/mosra/19abea23cdf6b82ce891c9410612e7e1

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