Git提交对部分存储库的访问
假设我有一个包含两个目录的回购协议,high_level/和low_level/。 我有一个投稿人想要提交访问权限,但我只觉得让他们接触高层/目录很舒服(而且他们只想) 必须四处奔波以恢复疯狂的提交会给您带来太多不便Git提交对部分存储库的访问,git,commit,Git,Commit,假设我有一个包含两个目录的回购协议,high_level/和low_level/。 我有一个投稿人想要提交访问权限,但我只觉得让他们接触高层/目录很舒服(而且他们只想) 必须四处奔波以恢复疯狂的提交会给您带来太多不便 是否可以在不拆分存储库的情况下执行此操作?我不知道任何开箱即用的方法。您可能会编写一个钩子脚本来在主repo中执行此操作,但感觉这样做的正确方法是根本不允许此参与者提交到存储库 相反,让他们对自己的存储库进行提交,然后您可以将您想要的内容拉入主repo。这样,您就可以完全控制他的承
是否可以在不拆分存储库的情况下执行此操作?我不知道任何开箱即用的方法。您可能会编写一个钩子脚本来在主repo中执行此操作,但感觉这样做的正确方法是根本不允许此参与者提交到存储库 相反,让他们对自己的存储库进行提交,然后您可以将您想要的内容拉入主repo。这样,您就可以完全控制他的承诺如何以及何时进入您的回购协议(如果不符合您的标准,也可以不这样做) 如果您确实需要此功能,建议的@SLaks“子模块”功能可能满足您的需要;实际上,您可以将“高级别”视为一个单独的项目,映射到“低级别”存储库中。然后他可以提交到高级存储库,而您可以将这些提交拉到低级存储库中。请参见使用预接收挂钩可以实现这一点,但它没有内置功能 要在预接收钩子中执行此操作,请让钩子扫描建议的标签更新,例如:
#! /bin/sh
...
while read oldsha newsha fullref; do
verify $oldsha $newsha $fullref || {
echo "$fullref: $oldsha -> $newsha update rejected"
exit 1
}
done
您仍然需要编写verify()函数:
NULL_SHA1=0000000000000000000000000000000000000000 # 40 0's
reftype() {
case $1 in
$NULL_SHA1) echo none;;
*) git cat-file -t $1;;
}
verify() {
local oldsha=$1 newsha=$2 fullref=$3
local otype=$(reftype $oldsha) ntype=$(reftype $newsha)
local update_type
case $otype,$ntype in
none,*) update_type=create;;
*,none) update_type=delete;;
*,*) update_type=update;;
esac
# now if update_type is create or delete, check permissions
# but if update_type is update, check revisions
verify_$update_type $oldsha $newsha $fullref
}
(上面的内容可能更复杂,例如,可以检查带注释的标记的创建/删除,并且可以检查ref类型与对象类型。)
这个“verify”只返回相应的更具体的verify\u create、verify\u delete或verify\u update返回的内容。所以你必须写下这些:
verify_create() {
local oldsha=$1 newsha=$2 fullref=$3
# only $USER = wilma is allowed to create
[ "$USER" = wilma ] && return 0
echo "you ($USER) are not allowed to create things"
return 1
}
verify_delete() {
local oldsha=$1 newsha=$2 fullref=$3
# only $USER = fred is allowed to delete
[ "$USER" = fred ] && return 0
echo "you ($USER) are not allowed to delete things"
return 1
}
现在我们开始验证\u更新:
verify_update() {
local oldsha=$1 newsha=$2 fullref=$3
local shortref rev
case "$fullref" in
refs/heads/*)
# a branch
shortref=${fullref#refs/heads/}
;;
*) # everything else - only barney is allowed to do those
# (and we don't check any further)
[ "$USER" = barney ] && return 0
echo "you ($USER) are not allowed to modify $fullref"
return 1
;;
esac
# user betty is restricted on branches that do not start with betty*
# everyone else is unrestricted
[ "$USER" = betty ] || return 0
case "$shortref" in
betty*) return 0;;
esac
# 1. betty is NOT allowed to REMOVE commits, even with force-push
if [ $(git rev-list --count $newsha..$oldsha) -ne 0 ]; then
echo "commit to branch $shortref would remove some revs"
return 1
fi
# 2. betty is not allowed to make certain changes
# e.g., first we forbid merges:
if [ $(git rev-list --count --min-parents=2 \
$oldsha..$newsha) -ne 0 ]; then
echo "you ($USER) are not allowed to push a merge"
return 1
fi
# then we look at each commit
for rev in $(git rev-list $oldsha..$newsha); do
check_betty_commit $rev "$shortref" || return 1
done
}
呼,我们快到了。只需检查贝蒂提出的改变:
check_betty_commit() {
local rev=$1 shortref="$2"
# unfortunately, pipe to a loop causes the loop to
# run in a sub-shell, so it's a bit complicated here.
git diff-tree -r --no-renames --name-only --no-commit-id $rev |
(retval=0; while read pathname; do
case "$pathname" in
forbidden/path/*)
echo "branch $shortref: $rev modifies $pathname"
retval=1
;;
esac
done
exit $retval) || return 1
}
注:以上大部分未经测试
硬编码用户名也可能不好。但是如果你真的想这样做的话,这应该会给你一些关于如何编写脚本的想法
顺便说一句,有一个不同的(但经过更多测试的)脚本,它根据存储库本身的设置实现一组有限的每用户访问控制,而不是对它们进行硬编码。考虑使用子模块。Git不规范这一点,因此您可以查看外部工具,如Gitolite。也就是说,也许你应该考虑只接受来自提交者的补丁,这样他们就不必拥有对你的存储库的写访问权限(他们可以克隆它,并对自己的私有副本执行他们认为必要的操作)。是的,这就是现在正在做的,但它没有回答问题。:)答案是“不”。)建议的SLaks“子模块”功能可能满足您的需要;实际上,您可以将“高级别”视为一个单独的项目,映射到“低级别”存储库中。然后他可以提交到高级存储库,而您可以将这些提交拉到低级存储库中。好吧,你可以加上它作为答案。:-)