How can I allow git merge commits to master but prevent non-merge commits?

I have a Git pre-commit hook that prevents me from committing to master unless overridden, in order to encourage developing on branch.

However I would like to automatically allow merge commits to master. Is there a way to identify a merge commit from my pre-commit hook script? The script looks like this:

  • Git as a backup and Version Control System
  • Git fails when pushing commit to github
  • Can git retain file owner, permissions, ACLs, and file attributes on a local Windows NTFS machine?
  • Can a git project track a directory listed in my global gitignore?
  • git: how can i list new files to add them after?
  • Composer pulling latest commits on separate repos
  • #!/bin/bash
    
    BRANCH=`git branch --color=never| grep '^*'|cut -c3-`
    
    if [ "${BRANCH}D" == "masterD" -a "${GIT_COMMIT_TO_MASTER}D" != "trueD" ]
    then
      echo "Commit directly to master is discouraged."
      echo "If you want to do this, please set GIT_COMMIT_TO_MASTER=true and then commit."
      exit 1
    fi
    

    SOLVED: For anyone looking for a cut-and-paste, the working version of this hook script is:

    #!/bin/bash
    
    BRANCH=$(git rev-parse --abbrev-ref HEAD)
    
    if [ "${BRANCH}" == "master" -a "${GIT_COMMIT_TO_MASTER}" != "true" ]
    then
      if [ -e "${GIT_DIR}/MERGE_MODE" ]
      then
        echo "Merge to master is allowed."
        exit 0
      else
        echo "Commit directly to master is discouraged."
        echo "If you want to do this, please set GIT_COMMIT_TO_MASTER=true and then commit."
        exit 1
      fi
    fi
    

  • Git has forgotten the remote repository I fetch from / push to
  • Is there lightweight git client for Windows?
  • Heroku Push Failed
  • To git checkout without overwriting data
  • Python Development Module Path
  • Batch script pass variable to stdin with git and ssh keys
  • One Solution collect form web for “How can I allow git merge commits to master but prevent non-merge commits?”

    I put a few comments in, but the important one here is that in a pre-commit hook, the commit you’re about to test does not yet exist, so you can’t count its parents.

    Here’s what you do get:

    • If you’re using git commit --amend to amend a merge commit, the pre-commit hook is run as usual, but it can’t really detect that this is happening. The new commit will be a merge, but you can’t tell.

    • If you’re using regular old git commit to create a non-merge commit, the file MERGE_HEAD will not exist in the git directory, and you can tell that this is not going to create a merge commit.

    • If you’re using git commit to finish off a conflicted merge, the file MERGE_HEAD will exist, and you can tell that this is going to create a merge commit.

    • If you’re running git merge and it succeeds on its own, it makes a new commit without using the pre-commit hook, so you don’t even get invoked here.

    Hence, if you’re willing to allow git commit --amend on merges to misfire, you can get close to what you want: just test for the existence of $GIT_DIR/MERGE_HEAD to see if this is a git commit that is finishing off a conflicted merge. (The use of $GIT_DIR is a trick to make this work even if the commands are run outside the git tree. Git sets $GIT_DIR so that in-hook git commands will work right.)

    Git Baby is a git and github fan, let's start git clone.