我在git远程分支上创建pre-receive
挂钩时出了问题,做了我想做的事。
问题是什么?
不应允许直接提交到主分支。只允许合并到主分支中。
解决方案
到目前为止,我的解决方案是检查主用户受到影响的用户推送是否有变化。但问题是,如果更改是直接提交或合并,我无法区分。
#!/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
有没有人知道,如何检查更改是否合并?
谢谢!
答案 0 :(得分:7)
这里是简短的回答:看看产生的价值:
git rev-list --count --max-parents=1 $oldrefid..$newrefid
你希望这个为零。继续阅读解释(和警告)。
你的循环有正确的轮廓:
诀窍在于执行检查。考虑一下您收到的另外两条信息,即旧的和新的SHA-1 ID,在这些钩子中,这两个SHA-1 ID中的一个(但不是两个)可能都是0
s(意思是正在创建或删除引用。)
要坚持认为更改不是创建或删除,您的测试应确保SHA-1都不是全零。 (如果您愿意假设只需要检查删除,那么您可以检查新的SHA-1是否全为零。但是如果可以进行创建 - 只有在某种情况下{{1毕竟,分支被删除,例如,登录到服务器接收推送的人,并手动删除它 - 你仍然需要确保旧的SHA-1不是全零的最终测试显然,这种删除是可能的,问题是你是否想编写代码来处理这种情况。)
在任何情况下,最典型的推送只是更新参考。请注意,任何新的提交都已写入存储库(如果您拒绝推送,它们将被垃圾收集),因此您的任务是:
要查找这两组提交,您应该使用master
,因为这正是它的工作:生成由某个表达式指定的SHA-1列表。这里你想要的两个表达式是#34;所有提交ID都可以从一个修订版中找到,但是还没有从其他ID"中找到它们。在git rev-list
个术语中,对于两个修订说明符git rev-list
和git rev-list $r1 ^$r2
,这些git rev-list $r2..$r1
, 1 或等效$r1
。当然,这两个revspecs只是建议的$r2
的旧ID和新ID。
这两个ID的顺序决定了哪一组提交push
列出:将被删除的那些 - 这个集合对于快进操作是空的 - 以及将要添加的那些。
在这个特定的情况下,你的目标不是自己生成这些提交列表(虽然这样可行),而是从这些列表中选择。
您可能希望阻止提交删除(即,即使执行git rev-list
的用户指定了强制标志,也要强制执行快进操作)。在这种情况下,只需验证要删除的""列表是空的就够了。你可以通过确保列表实际上是空的,或者在shell脚本中更简单来做到这一点 - 让push
为你计算它们并检查结果数是否为零。
您肯定希望阻止不合并的添加内容,但允许添加内容。在这种情况下,添加git rev-list
(也可以拼写--max-parents=1
)告诉--no-merges
禁止具有两个或更多父项的提交,即合并。添加git rev-list
可以获得满足此要求的提交计数,而不是合并,因为零或一个父级"约束。如果此计数为零,则根据定义添加的任何提交必须合并。
因此:
--count
例如,足以强制执行此特定约束。
1 几乎但不完全相同,你可以写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
:不同之处在于git rev-list $r1 --not $r2
的效果徘徊,所以如果你要添加另一个修订版身份--not
$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
被反转。
答案 1 :(得分:4)
您在预接收挂钩中获得的是分支的前一个和新的提示,因此您将不得不检查已添加的提交列表,并查看它们中的任何一个是否未合并:
nonmerges=$(git rev-list --no-merges --first-parent $oldrefid..$newrefid | wc -l)
[ "$nonmerges" -eq 0 ] && exit 0
--first-parent
将输出限制为来自主线的提交,即跳过已合并的提交(可通过second / third / ... parent访问)。
可能是复杂化:快进合并(很难与一系列正常提交区分开来)。