Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
788 views
in Technique[技术] by (71.8m points)

git - pre-receive hook on server-side that refuse any push to master which has any non-linear history

I am looking for a shell script (sh, not bash possibly) that would refuse any push to master which has any non-linear history.

I tried script from:

How to avoid "Merge branch 'master' of ssh://gdcm.git.sourceforge.net/gitroot/gdcm/gdcm"

which is implemented in ruby, but it does not even run on sourceforge server. I tried then the bash equivalent:

https://fedorahosted.org/fedora-infrastructure/attachment/ticket/1342/pre-receive

this one runs, but does not do what it is supposed to do (it does not reject anything).

Thanks for suggestions.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do this much, much more simply than your hook.

merge_commit=$(git rev-list -n 1 --merges $rev_old..$rev_new)
if [ -n "$merge_commit" ]; then
     echo "Merge commit detected: $merge_commit";
     exit 1
fi

You also might want to make this an update hook, not a pre-receive hook. The pre-receive hook runs once for the entire push, taking input on stdin, while the update hook runs once per ref to be updated, taking input as arguments. That gives you better granularity.

#!/bin/sh
ref=$1
rev_old=$2
rev_new=$3
if [ "$ref" = refs/heads/master ]; then
    ...
fi

There's also usually no need to check for fast forwards. Git already by default disallows non-fast-forward pushes, and if you want to deny them even on forced pushes, just set receive.denyNonFastForwards to true in the config. I guess you want to deny them even for forced pushes to master, but allow them elsewhere? That's a kind of access control that's actually implemented very well by things like gitolite, if you're doing your own hosting, but I guess if that's your requirement and you don't have gitolite, this is the best you can do.

Finally, it also strikes me as odd that you'll allow merge commits to be pushed to other refs, just not master. That could lead to some surprises, if someone pushes to an unstable branch, it gets tested, then you want it on master - but can't push it there!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...