Wintus
7/9/2014 - 8:53 PM

Git hook to prevent merging staging branch into master branch

Git hook to prevent merging staging branch into master branch

#!/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

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