Mar*_*zer 8 git git-merge githooks git-commit
我pre-receive在git远程分支上创建一个钩子有问题,做我想要的.
有什么问题?
不允许直接提交到主分支.只允许合并到主分支中.
解
到目前为止,我的解决方案是检查主用户受到影响的用户推送是否有变化.但问题是,如果更改是直接提交或合并,我无法区分.
#!/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
Run Code Online (Sandbox Code Playgroud)
有谁有想法,如何检查更改是否合并?
谢谢!
这是简短的回答:看看产生的价值:
git rev-list --count --max-parents=1 $oldrefid..$newrefid
Run Code Online (Sandbox Code Playgroud)
你希望这个为零.继续阅读解释(和警告).
你的循环有正确的轮廓:
诀窍在于执行检查.考虑一下您收到的另外两条信息,即旧的和新的SHA-1 ID,并且在这些钩子中,这两个SHA-1 ID中的一个(但不是两个)可能都是0s(意味着正在创建ref)或删除).
要坚持认为更改不是创建或删除,您的测试应确保SHA-1都不是全零.(如果你愿意假设只需要检查删除,你可以检查新的SHA-1不是全零.但是如果可以进行创建 - 只有在某种情况下master分支被删除后才会出现这种情况例如,某人登录到服务器接收推送,并手动删除它 - 你仍然需要确保旧的SHA-1不是全零的最终测试.显然这种删除是可能的,问题是你是否想编写代码来处理这个案子.)
在任何情况下,最典型的推送只是更新引用.请注意,任何新的提交都已写入存储库(如果拒绝推送,它们将被垃圾收集),因此您的任务是:
要找到这两组提交,您应该使用git rev-list,因为这正是它的工作:生成由某个表达式指定的SHA-1列表.您在此处需要的两个表达式是"所有提交ID都可以从一个修订版中找到,但尚未从其他ID中找到".在git rev-list条款这些git rev-list $r1 ^$r2,1或者等价地,git rev-list $r2..$r1对于两个修订说明符$r1和$r2.当然,这两个revspecs只是建议的旧ID和新ID push.
这两个ID的顺序决定了哪些提交git rev-list列表:将被删除的那些 - 这个集合对于快进操作是空的 - 以及将要添加的那些.
在这种特殊情况下,您的目标不是自己生成这些提交列表(虽然这样可行),而是从这些列表中选择一些内容.
您可能希望阻止提交删除(即,即使用户执行push指定的强制标志,也要强制执行快速转发).在这种情况下,只需验证"要删除"列表是否为空就足够了.您可以通过确保列表实际为空,或者在shell脚本中更简单 - git rev-list为您计算它们并检查结果数字是否为零来实现.
您肯定希望阻止不合并的添加,但允许添加.在这种情况下,添加--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
Run Code Online (Sandbox Code Playgroud)
例如,足以强制执行此特定约束.
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颠倒.
您在预接收挂钩中获得的是分支的前一个和新提示,因此您必须检查添加的提交列表,并查看其中是否有任何未合并:
nonmerges=$(git rev-list --no-merges --first-parent $oldrefid..$newrefid | wc -l)
[ "$nonmerges" -eq 0 ] && exit 0
Run Code Online (Sandbox Code Playgroud)
--first-parent将输出限制为来自主线的提交,即跳过合并的提交(可通过第二/第三/...父级访问)。
可能很复杂:快进合并(很难与一系列正常提交区分开来)。
| 归档时间: |
|
| 查看次数: |
1818 次 |
| 最近记录: |