Вы можете сделать это намного, намного проще, чем ваш хук.
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
Вы также можете захотеть сделать это хуком обновления, а не хуком предварительного получения. Хук предварительного получения запускается один раз для всего push, принимая входные данные в stdin, в то время как хук обновления запускается один раз для ref, обновляемого, принимая входные данные в качестве аргументов. Это дает вам лучшую гранулярность.
#!/bin/sh
ref=$1
rev_old=$2
rev_new=$3
if [ "$ref" = refs/heads/master ]; then
...
fi
Обычно нет необходимости проверять быстрые форварды. Git уже по умолчанию запрещает нажатия без ускоренной перемотки вперед, и если вы хотите запретить их даже при принудительном нажатии, просто установите receive.denyNonFastForwards
в значение true в конфигурации. Я предполагаю, что вы хотите отрицать их даже для принудительных толчков, но позволите им в другом месте? Это своего рода контроль доступа, который на самом деле очень хорошо реализован такими вещами, как gitolite, если вы делаете свой собственный хостинг, но я думаю, если это ваше требование, и у вас нет gitolite, это лучшее, что вы можете сделать.
Наконец, мне также кажется странным, что вы позволите коммитам слияния передаваться другим реферам, но не хозяину. Это может привести к некоторым сюрпризам: если кто-то протолкнет нестабильную ветку, она будет проверена, то вы захотите ее на главном сервере - но не можете ее туда вставить!