关于在git中设置预接收挂钩的查询
我想设置一个预接收挂钩,其逻辑如下关于在git中设置预接收挂钩的查询,git,Git,我想设置一个预接收挂钩,其逻辑如下 检查是否存在任何合并提交 检查是否推送了新分支 检查是否有多个提交 如果存在上述任何一项,则与用户交互,与用户确认他是否愿意推动更改,如果愿意,则推动更改,否则放弃更改 在git中的预接收钩子中是否有可能实现上述功能?您不能在预接收钩子中与用户交互,至少一般不能,因为用户可能在其他机器上执行“ssh”,并且标准输入不会发送给用户。(你可以通过检查UID和/或用户名之类的东西来拼凑一些东西,然后跳转到一个“回调”用户的脚本中。我把这个方向的实验留给你。)不过
- 检查是否存在任何合并提交
- 检查是否推送了新分支
- 检查是否有多个提交
在git中的预接收钩子中是否有可能实现上述功能?您不能在预接收钩子中与用户交互,至少一般不能,因为用户可能在其他机器上执行“ssh”,并且标准输入不会发送给用户。(你可以通过检查UID和/或用户名之类的东西来拼凑一些东西,然后跳转到一个“回调”用户的脚本中。我把这个方向的实验留给你。)不过,你可以做所有这些检查 预接收挂钩(在stdin上)获得一系列行:
<old-value> SP <new-value> SP <ref-name> LF
然后将创建、删除或更新给定的分支。如果
为400
s,则正在创建分支;如果
为400
s,则将其删除;另外,它正在更新。(除了refs/heads/*,还有其他内容;有关完整列表,请参阅git发送电子邮件挂钩。)
如果分支正在更新,
是它用来指向的提交ID,
是允许更新时它将指向的提交ID(这取决于预接收挂钩和更新挂钩)
这里有一个钩子可以简单地检测第二个和第三个案例(加上删除)。要了解是否存在合并,您必须在$between
中查看每个版本,并查看是否有合并(即,有多个父级)。要停止提交,请退出非零而不是返回0
#! /bin/sh
check()
{
local old=$1 new=$2 longref=$3
local between rev
if expr $old : '^00*$' >/dev/null; then
echo creating new branch ${longref#refs/heads/}
return 0
fi
if expr $new : '^00*$' >/dev/null; then
echo removing branch ${longref#refs/heads/}
return 0
fi
between=$(git rev-list $old..$new)
case "$between" in
*$'\n'*)
echo at least two revs
for rev in $between; do git log -1 --oneline $rev; done
return 0
esac
echo only one rev
return 0
}
while read old new longref; do
case $longref in
refs/heads/*) check $old $new $longref;;
esac
done
(您可以检查$between
中的所有rev,因为它们已经发送到远程回购,即使您要拒绝它们)。
更新:我找到了一种方法,即使在使用ssh传输时也能做到这一点,因为ssh传输不允许您走私任何额外的数据 我修改(并重命名)了
check
函数。在新名称下,get_confirmation
,意味着在默认情况下不允许推送的情况下(并返回0)(在允许推送的情况下返回1)
然后,在主循环中,您可以执行以下操作:
case $longref in
refs/heads/*)
if get_confirmation $old $new $longref; then
case $PWD in
*.allow.git)
echo 'allowed via alternate path'
;;
*.git)
echo "denied ... push to ${PWD%.git}.allow.git to allow"
exit 1
;;
*)
echo "denied, don't know where I am"
exit 1
;;
esac
fi
;;
# add more cases here if desired
esac
这假设您推送到一个--bare
克隆,该克隆位于/some/path/to/repo.git
中
要创建允许推送的等效repo,您必须创建一个实际的并行目录,其名称以repo.allow.git
结尾。该目录应包含一个实际文件,HEAD
,该文件是从普通repo复制的;目录中的所有内容都可以是指向。/repo.git/
的符号链接:
HEAD
必须是一个普通文件的原因是,否则git push
不会将其视为有效的回购(只有当它是到分支的链接时才允许是符号链接,这是执行符号引用的“旧方法”)
常规的git推送
失败,您可以改为git推送remotehost:/some/path/to/repo.allow.git
,使其通过。当然,你的用户可能会养成一直这样做的习惯,从而避免了这种黑客行为的全部目的,但也许他们不会
当然,这一切都假定您的远程repo是一个类似Unix的主机(即支持符号链接)。Torek谢谢。我试试这个。另一种使钩子交互的方法是使用“exec
exec
中提到的技巧,在本地运行的钩子中也可以,但是预接收通常在远程机器上运行,并使用非交互ssh:git push
<代码>远程:挂钩/预接收:第30行:/dev/tty:未配置设备
case $longref in
refs/heads/*)
if get_confirmation $old $new $longref; then
case $PWD in
*.allow.git)
echo 'allowed via alternate path'
;;
*.git)
echo "denied ... push to ${PWD%.git}.allow.git to allow"
exit 1
;;
*)
echo "denied, don't know where I am"
exit 1
;;
esac
fi
;;
# add more cases here if desired
esac
cd /some/path/to
mkdir repo.allow.git
cd repo.allow.git
ln -s ../repo.git/* .
rm HEAD; cp ../repo.git/HEAD .