What I want to do:
I want to disallow any merge commits to be pushed to the central repository. The only exception being if the merge is between branches that exist in the central repository. I want to enforce this at the central repository.
Explanation of why I want to do this:
Note: If this explanation throws you off the trail of what I want to do, then ignore the explanation. Of course I'm happy to hear other ways to solve the issue I explain below, but the answer I'm interested in is to what I want to do as stated above.
I have a central git repository with a branch that several developers track. Each developer has a remote configured for that central repository's branch.
We follow a synchronous commit policy for this project, so each developer must always rebase their latest work on top of the remote branch HEAD before pushing. I would like to enforce this policy by disallowing any merge commits to ever be pushed to the central repository. The only exception being if the merge is between branches that exist in the central repository.
To simplify, I do not want developer's local tracking branches to ever be merged with the remote branch. But rather always be rebased on the remote branch.
We've partly enforced this on the developer's machine by setting branch.NAME.rebase = true which helps avoiding problems if the developer uses git pull, however we need a solution to enforce this on the central repository side.
A very base solution would be to refuse commits with the comment: "Merge branch 'NAME' of GITURL", however, something more along the lines of checking if all parents of a commit exist in the central repository's branch paths would be more interesting.
Suggestions? Solutions?
Edit:
This is what I have so far:
#!/bin/sh
read sha1old sha1new refname
# check if this is merge commit
merge_commit="`git rev-list --parents --merges --no-walk $sha1new 2> /dev/null`"
if test -n "$merge_commit"
then
# this was a merge commit
# $merge_commit contains: sha1new sha1parent_1 ... sha1parent_n
fi
exit 0
The place it gets troublesome is determining whether the ancestry of any two parents originate from a single branch. Also, because pre-receive hook is called before any refs are updated, if a push contains commits for two branches that exist in the remote, including a merge between those two branches, then I have no idea what the solution would be here...