As git is distributed, there is no way to prohibit users to do it locally, and I'm not even sure if it's possible with local hooks.
And because a user doesn't have to push all local refs, there is no way to prevent it on the server either.
Edit:
You are talking about mistakes. Git allows users to fix their mistakes and undo the error, but that requires them to notice it. Like I said in the comments you could try to use hooks for this, but there is no pre-merge hook or something.
If I understood correctly, this is your situation:
,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´
After some common history (o), you committed and pushed your work (y). Your coworker (c) did work on his local repository and did a bad merge (M).
Afterwards there might be some additional commits (a) on top of M.
git reset --hard develop M^2
git branch coworker M^1
Now your graph looks exactly like before the bad merge:
,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop
Do a good merge (G):
git checkout develop
git merge coworker
Resulting in:
,-c--c--c--c-、
o--o--y--y--y--y--G ← develop
Now transplant the additional commits:
git reset --hard X
git rebase --onto G M develop
This gives the final result:
,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop
Be aware that this might result in more merge conflicts. Also you just changed history, i.e. all your coworkers should clone/reset/rebase to the new history.
PS: of course you should replace G
, M
and X
in your commands by the corresponding commit id.
Best Answer
It's kinda in the nature of a DVCS that the action happens on a local machine, and gets pushed back to the main repo.
If it's that onerous, script it.