Git:预接收钩子,只允许合并,不允许直接提交到主服务器
我在git远程分支上创建Git:预接收钩子,只允许合并,不允许直接提交到主服务器,git,git-merge,githooks,git-commit,Git,Git Merge,Githooks,Git Commit,我在git远程分支上创建预接收钩子时遇到了一个问题,我想怎么做就怎么做 有什么问题吗? 不允许直接提交到主分支。只允许合并到主分支中 解决方案 到目前为止,我的解决方案是检查来自用户的推送是否有变化,主推送是否受到影响。但问题是,我无法区分更改是直接提交还是合并 #!/bin/sh while read oldrefid newrefid refname do if [ "$refname" = "refs/heads/master" ]; then echo $(git mer
预接收
钩子时遇到了一个问题,我想怎么做就怎么做
有什么问题吗?
不允许直接提交到主分支。只允许合并到主分支中
解决方案
到目前为止,我的解决方案是检查来自用户的推送是否有变化,主推送是否受到影响。但问题是,我无法区分更改是直接提交还是合并
#!/bin/sh
while read oldrefid newrefid refname
do
if [ "$refname" = "refs/heads/master" ]; then
echo $(git merge-base $oldrefid $newrefid)
echo "---- Direct commit to master branch is not allowed ----"
echo "Changes only with a merge from another branch"
exit 1
fi
done
有人知道如何检查更改是否为合并吗
谢谢大家! 在预接收钩子中得到的是分支的上一个和新的提示,因此您必须检查已添加的提交列表,并查看是否有任何提交不是合并:
nonmerges=$(git rev-list --no-merges --first-parent $oldrefid..$newrefid | wc -l)
[ "$nonmerges" -eq 0 ] && exit 0
--第一个父级
将输出限制为从主线提交,即跳过合并到的提交(可通过第二个/第三个/…父级访问)
可能的复杂性:快进合并(很难与一系列正常提交区分)。这里有一个简短的答案:看看由以下内容生成的值:
git rev-list --count --max-parents=1 $oldrefid..$newrefid
你希望这是零。请继续阅读解释(和注意事项)
您的循环具有正确的轮廓:
- 读取所有ref更新李>
- 对于那些更新您关心的分支(或其他引用)的分支,请执行一些检查
主
分支最终以某种方式被删除时才会发生这种情况,例如,有人登录服务器接收推送,然后手动删除它,您仍然需要确保旧的SHA-1在最终测试中不全为零。显然,这种删除是可能的,问题是您是否要编写代码来处理这种情况。)
在任何情况下,最典型的推送都只是更新引用。请注意,任何新提交都已写入存储库(如果拒绝推送,它们将被垃圾收集),因此此时您的任务是:
- 查找并验证引用用于命名的、它将不再命名的任何提交(这些提交将被非快进推送删除);及
- 查找并验证引用现在将命名的、它不用于命名的任何提交(这些是推送将添加的新提交,无论是否快进:请记住,新推送可以在添加一个或多个提交的同时删除一个或多个提交)
git rev list
,因为这正是它的工作:生成由某个表达式指定的SHA-1列表。这里需要的两个表达式是“所有提交ID都可以从一个版本中找到,而这些ID还不能从其他ID中找到”。在git rev list
术语中,这些术语是git rev list$r1^$r2
,1或相当于git rev list$r2..$r1
,用于两个版本说明符$r1
和$r2
。当然,这两个revspec只是建议的push
的新旧ID
这两个ID的顺序决定了哪个提交集git rev list
列出:对于快进操作,将被删除的提交集为空,将被添加的提交集为空
在这种特殊情况下,您的目标不是生成这些提交列表(尽管这样做可行),而是从这些列表中选择一些内容 您可能希望防止提交删除(即,即使执行
push
的用户指定了强制标志,也要强制快进)。在这种情况下,只需验证“待删除”列表是否为空就足够了。您可以通过确保列表实际上是空的,或者在具有git rev list
的shell脚本中更简单,为您计算它们并检查结果是否为零
您肯定希望防止非合并的添加,但允许合并的添加。在这种情况下,添加--max parents=1
(也可以拼写为--no merges
)会告诉git rev list
禁止具有两个或多个父级的提交,即合并。添加--count
可获得满足此“非合并,因为零或一个父项”约束的提交计数。如果此计数为零,则根据定义,添加的任何提交都必须是合并
因此:
n=$(git rev-list --count --max-parents=1 $oldrefid..$newrefid)
if [ $n -gt 0 ]; then
echo "disallowed: push adds $n non-merge commit(s)" 1>&2
exit 1
fi
例如,将足以强制执行此特定约束
1您可以编写
git rev list$r1--not$r2
:不同之处在于--not
的效果仍然存在,因此如果您要添加另一个修订ID$r3
,--not
将应用于r3
。也就是说,git rev list A^B C
表示yes-A、not-B、yes-C
但A--not B C
表示yes-A、not-B、not-C
。请注意,在rev list
语法中,B..A
意味着A^B
,也就是说,B
完全是反向的。“快进合并(很难与一系列正常的提交进行区分)”AFAIK无法区分一系列提交和快进合并。它只是我们合并到的分支的一个更新,用于提交所讨论的内容。@Zeeker您可以使用-g