Skip to content

Instantly share code, notes, and snippets.

@mosra
Forked from ColCh/README.md
Last active October 9, 2024 03:47
Show Gist options
  • Save mosra/19abea23cdf6b82ce891c9410612e7e1 to your computer and use it in GitHub Desktop.
Save mosra/19abea23cdf6b82ce891c9410612e7e1 to your computer and use it in GitHub Desktop.
Git pre-push hook to confirm pushing to master

Git pre-push hook

Checks if the remote branch is master, then asks a confirmation. Based on https://gist.github.com/ColCh/9d48693276aac50cac37a9fce23f9bda, but modified to check the remote name instead of local, making it work also for the really dangerous accidents like below:

git push -f origin e09b7418a310114f6aaf495f969c3859095a99af:master

Further info: https://dev.ghost.org/prevent-master-push/, https://coderwall.com/p/jp7d5q/create-a-global-git-commit-hook, https://git-scm.com/docs/githooks#_pre_push, https://stackoverflow.com/questions/22585091/git-hooks-pre-push-script-does-not-receive-input-via-stdin

Installation

  1. Enable git templates

    git config --global init.templatedir '~/.git-templates'
  2. Create a directory to hold the global hooks:

    mkdir -p ~/.git-templates/hooks
  3. Copy the pre-push file from below into ~/.git-templates/hooks/pre-push

  4. Make it executable

    chmod +x ~/.git-templates/hooks/pre-push
  5. In currently existing project, do a reinit. This will not overwrite existing commits, or existing hooks -- so if you already have a pre-push hook, you may need to merge the two together.

    git init

Done!

#!/bin/bash
# Add more branches separated by | if needed
protected_branches='master|main'
# Argument parsing taken from .git/hooks/pre-push.sample
if read local_ref local_sha remote_ref remote_sha; then
if [[ "$remote_ref" =~ ($protected_branches) ]]; then
echo -en "\033[1;33mYou're about to push to $remote_ref, 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
@BossElijah
Copy link

Thanks for this @mosra! How would I do if I want to protect multiple branches (e.g. main and master)?

@mosra
Copy link
Author

mosra commented Aug 1, 2024

Edited to handle that :)

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