Is there a way to configure git repository to reject 'git push --force'?

Solution 1:

Setting the configuration variables:

receive.denyNonFastForwards
receive.denyDeletes

will prevent any 'forced' pushes from working across all branches.

If you want finer pre-branch control then you will have to use a 'hook' on the remote repository, probably the 'update' hook.

There is a sample update hook called 'update-paranoid' that probably does what you need (and more) in the git distribution in the 'contrib' folder.

gitweb link

Solution 2:

Github has already introduced the concept of protected branches!

It can be found under Settings -> Branches -> Protected Branches. Feature is now available for all users - not only enterprise!

This "protection" can be enabled for any branch, and for any user, including admins.

More details here - https://help.github.com/articles/defining-the-mergeability-of-pull-requests/

So no more hooks and arbitrary code is needed.

Solution 3:

I wrote this quick update hook to prevent non-fast-forward updates (pushes) on the "dev" branch in a repository:

#!/bin/sh

REFNAME=$1
OLDSHA=$2
NEWSHA=$3

if [ "refs/heads/dev" != $REFNAME ]; then
  exit 0
fi

MERGEBASE=$(git merge-base $OLDSHA $NEWSHA)
if [ $OLDSHA = $MERGEBASE ]; then
  exit 0
fi

echo "Not a fast-forward on branch dev"
exit 1