我正在寻找一个shell脚本(sh
,而不是bash
),拒绝任何具有任何非线性历史记录的 master 的推送。
我尝试了以下脚本:
How to avoid "Merge branch 'master' of ssh://gdcm.git.sourceforge.net/gitroot/gdcm/gdcm"
在ruby
中实现,但它甚至不在sourceforge服务器上运行。我尝试了bash等价物:
https://fedorahosted.org/fedora-infrastructure/attachment/ticket/1342/pre-receive
这个运行,但没有做它应该做的事情(它不会拒绝任何东西)。
感谢您的建议。
答案 0 :(得分:3)
你可以做得这么多,比你的钩子更简单。
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
您也可能希望将其设为更新挂钩,而不是预先接收挂钩。预接收挂钩为整个推送运行一次,在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,这是你能做的最好的。
最后,它也让我感到奇怪,你将允许将合并提交推送到其他引用,而不是主。这可能会导致一些意外,如果有人推送到不稳定的分支,它会接受测试,然后你想要它在主人身上 - 但不能把它推到那里!
答案 1 :(得分:2)
在sourceforge服务器上经过多次努力之后,我得到了:
#!/bin/sh
# Author: Mathieu Malaterre
# This code is free software. It can be used and distributed under the
# same terms as git itself.
# http://stackoverflow.com/questions/5482887/how-to-avoid-merge-branch-master-of-ssh-gdcm-git-sourceforge-net-gitroot-gdc
read rev_old rev_new refname
ref_to_check="refs/heads/master"
if [ "$refname" = "$ref_to_check" ]
then
merge_bases=`git merge-base ${rev_old} ${rev_new}`
if [ "$merge_bases" != "$rev_old" ]
then
echo "Non fastward is disallowed"
exit 1
fi
# non-fast-forward case:
git rev-list --parents $merge_bases..$rev_new \
| while read x; do
set -- $x
if [ "$#" != "2" ]
then
echo "Multiple parents: $x";
exit 1
fi;
done
[ $? -ne 0 ] && exit 1
fi
exit 0
答案 2 :(得分:0)
此脚本对我有用!它可以保护选定的分支免遭强制推送和删除。
#!/bin/sh
_REFNAME="$(echo "${1}" | sed -e 's,[^/]\+/,,g')"
_OLDREF="${2}"
_NEWREF="${3}"
_PROTECTED_LIST=( 'master' 'develop' )
_PROTECTED=false
for ref in "${_PROTECTED_LIST[@]}"; do
if [[ "${ref}" == "${_REFNAME}" ]]; then
_PROTECTED=true
fi;
done;
echo ""
echo "#################### YOUR PROJECT NAME ####################"
echo "Branch: ${_REFNAME}"
echo "Old ref: ${_OLDREF}"
echo "New ref: ${_NEWREF}"
echo ""
_SUCCESS=true
if ${_PROTECTED}; then
_GITOUT="$(git merge-base ${_OLDREF} ${_NEWREF} 2>/dev/null)"
if [[ -n "${_GITOUT}" && "${_GITOUT}" != "${_OLDREF}" ]]; then
echo "ERROR! You can't force the push on this branch!"
_SUCCESS=false
fi;
if [[ -n "$(echo "${_NEWREF}" | sed -n -e '/^0\+$/p')" ]]; then
echo "ERROR! You can't delete this branch!"
_SUCCESS=false
fi;
fi;
if ${_SUCCESS}; then
echo "SUCCESS! :-)"
echo "See you later?"
echo ""
exit 0
fi;
echo ""
exit 1