Skip to content

Instantly share code, notes, and snippets.

Last active July 14, 2023 14:11
Show Gist options
  • Save mwise/69ec35b646b52d98050d to your computer and use it in GitHub Desktop.
Save mwise/69ec35b646b52d98050d to your computer and use it in GitHub Desktop.
Git hook to prevent merging staging branch into master branch

To use this hook:

  • add the prepare-commit-msg file at .git/hooks/prepare-commit-msg and edit as needed
  • make it executable: chmod +x .git/hooks/prepare-commit-msg
  • disable fast-forward merges: git config branch.master.mergeoptions "--no-ff"
  • that's it!

NOTE: after a failed merge from a forbidden branch, the working tree will still be in a MERGING state. To discard the local working copy state, run: git reset --merge

#!/usr/bin/env ruby
# This git hook will prevent merging specific branches into master
# Put this file in your local repo, in the .git/hooks folder
# and make sure it is executable.
# The name of the file *must* be "prepare-commit-msg" for Git to pick it up.
def merge?
ARGV[1] == "merge"
def into_master?
current_branch = `git branch | grep '*' | sed 's/* //'`.chop
current_branch == "master"
def merge_msg
@msg ||= `cat .git/MERGE_MSG`
def from_branch
@from_branch = merge_msg.match(/Merge branch '(.*?)'/)[1]
def from_forbidden_branch?
if merge? && into_master? && from_forbidden_branch?
out = `git reset --merge`
puts " You are trying to merge #{from_branch} into the *master* branch."
puts " Surely you don't mean that?"
puts " run the following command now to discard your working tree changes:"
puts " git reset --merge"
exit 1
Copy link

hujuice commented Dec 27, 2017

Hello Mark,
inspired from your script, I'll change the regex on line 24. Perhaps you are interested in why.
My git log is:

$ git log|grep -i merge
    QA added post-merge
Merge: 057f1d6 9524480
    Merge remote-tracking branch 'integration/testHook' into hooks   <----------------------------------------------
Merge: b07a491 484fbc8
Merge: fe292ef 91b3669
    Merge branch 'master' of
Merge: 11c7a4b 99cf90e
    Merge branch 'master' of ssh://

I don't know if git can give other attributes to the branch, so the regex will become something like /Merge .*?branch '(.*?)'/


Copy link

hujuice commented Dec 27, 2017

If you are interested, I wrote the same in Bash, as sayd.
My purpose was different: avoid merge from remote branches other than master to master, so the logic is a bit different.
Note that I've found three types of MERGE_MSG.

What I hate and I cannot resolve is the suggestion provided by git at the end: git encourages to perform the commit.
Git says «Not committing merge; use 'git commit' to complete the merge.» as very last line. Git has the last world, grrr.
Do you have ideas about?

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