block push of trivial merge to git server block push of trivial merge to git server bash bash

block push of trivial merge to git server


I came across this piece of code, while trying to find a solution. It doesn't do exactly what you want, but it should be ez to add extra branch names on the if statement.

Works for me, so far. it forces pull --rebase for the same branch and lets regular merges with other branches go through.

All credits go to the original author.

#!/bin/bash## This git update hook will refuse unnecessary merge commits caused by pulling# from being pushed to a shared repository. These commits make following the# history of a project difficult and are always avoidable with rebasing.## by Scott Kyle (appden)# modified by Olivier Refalo (orefalo)refname="$1"oldrev="$2"newrev="$3"# if this is not run as a hook, you may have messed upif [ -z "$GIT_DIR" -o -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then    echo "Usage: GIT_DIR=<path> $0 <ref> <oldrev> <newrev>" >&2    exit 1fi# if the new revision is all 0's then it's a commit to delete a refzero="0000000000000000000000000000000000000000"# also check if the new revision is not a commit or is not a fast forward# detect branch deletion, branch creation... and moreif [ "${refname#refs/heads/}" = "master" ] || [ "$newrev" = "$zero" ] || [ "$oldrev" = "$zero" ] || [ $(git cat-file -t $newrev) != "commit" ] || [ $(git merge-base $oldrev $newrev) != "$oldrev" ]; then    exit 0fi# loop through merges in the push only following first parentsfor merge in $(git rev-list --first-parent --merges $oldrev..$newrev --); do    # lazily create the revision list of this branch prior to the push    [ -z "$revlist" ] && revlist=$(git rev-list $oldrev)    # check if the second parent of the merge is already in this branch    if grep -q $(git rev-parse $merge^2) <<< "$revlist"; then        cat >&2 <<-EOF            *** PUSH REJECTED ***            *** TRIVIAL merge detected on local branch ${refname#refs/heads/}            *** To fix: git rebase origin/${refname#refs/heads/}            ***            *** Next time use: git pull --rebase            ***            *** Permanent fix: git config [--global] branch.autosetuprebase always            *** Then for existing branches: git config branch.<name>.rebase true        EOF        exit 1    fidoneecho -Info- Clean history successfully preserved!exit 0


This update hook will check if you are pushing to specific branches (it allows trivial merges in wip, topic and other branches).

This does not bother with the rest of the parents on octopus merges as it only references the 2nd parent in each merge commit being pushed. Please feel free to update the script.

UPDATE: Reserved branches are required to exist on the remote.

#!/bin/bashrefname="$1"oldrev="$2"newrev="$3"branches="refs/heads/hotfixes refs/heads/dev refs/heads/qa refs/heads/master"cont="no"for branch in $branches ; do  if [[ $refname == $branch ]] ; then    cont="yes"  fidoneif [[ $cont == "no" ]] ; then  exit 0fiecho "inspecting branch $refname for trivial merges" >&2hashes="$(git log --format=%H --merges $oldrev..$newrev)"for hash in $hashes ; do  echo "checking merge commit $hash" >&2  cont="no"  for branch in $branches ; do    if [[ $refname == $branch ]] ; then      continue    fi    # if [[ "$(git log --format=%H $hash^2 ^$branch | wc -l)" == "0" ]] ; then    if [[ "$(git log --format=%H $hash^2 ^$branch | wc -l)" == "    0" ]] ; then      cont="yes"    fi  done  if [[ $cont == "no" ]] ; then    echo "No trivial merges allowed. Please rebase and push again." >&2    exit 1  fidoneexit 0