如何防止非快进推送到git中的选定分支



我想保护我的git存储库,这样只有非主分支才能被覆盖。有没有办法只保护选定的分支?

这里有一个更新挂钩(复制到挂钩/update),我是为自己使用而写的。默认情况下,此脚本拒绝所有非快进更新,但允许显式配置的分支进行更新。反转它应该足够容易,这样除了主分支之外,所有分支都可以进行非快进更新。

#!/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

您可以使用GitEnterprise设置每分支权限(admin),以使用细粒度访问权限阻止非快进推送。

如果您需要阻止所有分支的历史更改,git config --system receive.denyNonFastForwards true将简单地完成这项工作。

您可以通过配置denyNonFastForwards 来防止非快进更新

git config --system receive.denyNonFastForwards true

但它适用于所有分支机构。有关更多信息,请参阅ProGit

我认为这取决于您在服务器端使用什么来访问存储库。有一些服务器应用程序支持每个分支的权限,比如Gerrit或Gitlab(但是,我不确定Gitlab是否支持您的用例)。Gerrit支持它,因为我在公司中使用类似的工作流程。

也许Gitolite也支持它(这是Gitlab在后台使用的),它更容易设置,但没有像Gerrit或Gitlab那样的网络接口。

附加评论:正如建议的那样,GitEnterprise也是一个很好的解决方案,但我的建议是合适的,如果你有自己的服务器(这在许多公司都很常见)。

如果允许您修改服务器,那么这将在服务器上实现快速转发。

ssh ip 'echo $"[receive]
    denyDeletes = false
    denyNonFastForwards = false" >> /path/to/repo/config'
#then git push -f origin master

这个SO答案将为您提供您想要的内容。只需将其编辑为应用于主分支即可:

#!/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

更新:
这将阻止所有对主分支的推送,包括快进。

这里是对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

相关内容

  • 没有找到相关文章

最新更新