Skip to content

Instantly share code, notes, and snippets.

@mwise
Last active July 14, 2023 14:11
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • 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.
FORBIDDEN_BRANCHES = ["staging"]
def merge?
ARGV[1] == "merge"
end
def into_master?
current_branch = `git branch | grep '*' | sed 's/* //'`.chop
current_branch == "master"
end
def merge_msg
@msg ||= `cat .git/MERGE_MSG`
end
def from_branch
@from_branch = merge_msg.match(/Merge branch '(.*?)'/)[1]
end
def from_forbidden_branch?
FORBIDDEN_BRANCHES.include?(from_branch)
end
if merge? && into_master? && from_forbidden_branch?
out = `git reset --merge`
puts
puts " STOP THE PRESSES!"
puts " You are trying to merge #{from_branch} into the *master* branch."
puts " Surely you don't mean that?"
puts
puts " run the following command now to discard your working tree changes:"
puts
puts " git reset --merge"
puts
exit 1
end
@hujuice
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 https://dev.contactcentre.istat.cheapguru.org/git
Merge: 11c7a4b 99cf90e
    Merge branch 'master' of ssh://head.inservibile.org/var/www/vhosts/istat/contactcentre

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

Regards,
HUjuice

@hujuice
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.
https://gist.github.com/hujuice/9ff2fd4221e2135f946931dbb512bfc6#file-prepare-commit-msg
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