Git提交对部分存储库的访问

Git提交对部分存储库的访问,git,commit,Git,Commit,假设我有一个包含两个目录的回购协议,high_level/和low_level/。 我有一个投稿人想要提交访问权限,但我只觉得让他们接触高层/目录很舒服(而且他们只想) 必须四处奔波以恢复疯狂的提交会给您带来太多不便 是否可以在不拆分存储库的情况下执行此操作?我不知道任何开箱即用的方法。您可能会编写一个钩子脚本来在主repo中执行此操作,但感觉这样做的正确方法是根本不允许此参与者提交到存储库 相反,让他们对自己的存储库进行提交,然后您可以将您想要的内容拉入主repo。这样,您就可以完全控制他的承

假设我有一个包含两个目录的回购协议,high_level/和low_level/。 我有一个投稿人想要提交访问权限,但我只觉得让他们接触高层/目录很舒服(而且他们只想)

必须四处奔波以恢复疯狂的提交会给您带来太多不便


是否可以在不拆分存储库的情况下执行此操作?

我不知道任何开箱即用的方法。您可能会编写一个钩子脚本来在主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“子模块”功能可能满足您的需要;实际上,您可以将“高级别”视为一个单独的项目,映射到“低级别”存储库中。然后他可以提交到高级存储库,而您可以将这些提交拉到低级存储库中。好吧,你可以加上它作为答案。:-)