我想保护我的git存储库,因此只能覆盖非主分支。有没有办法只保护选定的分支?
答案 0 :(得分:6)
这是我为自己编写的更新钩子(复制到钩子/更新)。默认情况下,此脚本拒绝所有非快进更新,但允许它们用于显式配置的分支。它应该很容易被反转,以便除了主分支以外的所有允许非快进更新。
#!/bin/sh
#
# A hook script to block non-fast-forward updates for branches that haven't
# been explicitly configured to allow it. Based on update.sample.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# Config
# ------
# hooks.branch.<name>.allownonfastforward
# This boolean sets whether non-fast-forward updates will be allowed for
# branch <name>. By default they won't be.
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
;;
refs/tags/*,delete)
# delete tag
;;
refs/tags/*,tag)
# annotated tag
;;
refs/heads/*,commit)
# branch
# git rev-list doesn't print anything on fast-forward updates
if test $(git rev-list "$newrev".."$oldrev"); then
branch=${refname##refs/heads/}
nonfastforwardallowed=$(git config --bool hooks.branch."$branch".allownonfastforward)
if [ "$nonfastforwardallowed" != "true" ]; then
echo "hooks/update: Non-fast-forward updates are not allowed for branch $branch"
exit 1
fi
fi
;;
refs/heads/*,delete)
# delete branch
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
;;
*)
# Anything else (is there anything else?)
echo "hooks/update: Unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0
答案 1 :(得分:4)
您可以使用GitEnterprise设置每个分支的权限(admin),以使用细粒度的访问权限阻止非快速推送。
如果您需要阻止所有分支的历史记录更改,git config --system receive.denyNonFastForwards true
将完成此任务。
答案 2 :(得分:1)
This SO answer会为您提供所需的信息。只需编辑它以应用于主分支:
#!/bin/sh
# lock the master branch for pushing
refname="$1"
if [ "$refname" = "refs/heads/master" ]
then
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
echo "You cannot push to the master branch."
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
exit 1
fi
exit 0
<强>更新强>
这将阻止所有推送到主分支,包括快进。
答案 3 :(得分:1)
您可以通过配置denyNonFastForwards
git config --system receive.denyNonFastForwards true
但它适用于所有分支机构。 有关详细信息,请参阅ProGit
答案 4 :(得分:0)
我认为这取决于您在服务器端使用什么来访问您的存储库。有一些服务器应用程序支持每个分支的权限,如Gerrit或Gitlab(但是,我不确定Gitlab是否支持您的用例)。 Gerrit支持它,因为我在公司使用类似的工作流程。
也许Gitolite也支持它(这就是Gitlab在幕后使用的),它更容易设置,但没有像Gerrit或Gitlab这样的网络界面。
补充评论:GitEnterprise,正如所建议的,也是一个很好的解决方案,但是我的建议是合适的,如果你有自己的服务器(这在许多公司很常见)。
答案 5 :(得分:0)
如果允许您修改服务器,则可以在服务器上启用快速转发。
ssh ip 'echo $"[receive]
denyDeletes = false
denyNonFastForwards = false" >> /path/to/repo/config'
#then git push -f origin master
答案 6 :(得分:0)
这里是Tanu Kaskinen脚本的修改,允许对分支名称进行通配符处理。我们使用名称以“ d /”开头的分支来指定“开发”分支。我想要一种允许对这些d /分支进行非快速更新的方法:
refs/heads/*,commit)
# branch
# git rev-list doesn't print anything on fast-forward updates
if [[ $(git rev-list "$newrev".."$oldrev") ]]; then
branch=${refname##refs/heads/}
if [[ "$branch" =~ ^d/ ]] ; then
echo "Non-fast-forward update allowed on d/ branch"
nonfastforwardallowed="true";
else
#look for a specific config setting
nonfastforwardallowed=$(git config --bool hooks.branch."$branch".allownonfastforward)
fi
if [ "$nonfastforwardallowed" != "true" ]; then
echo "hooks/update: Non-fast-forward updates are not allowed for branch $branch"
exit 1
fi
fi