我想设置预接收挂钩,这样做的逻辑
如果存在上述任何一项,则与用户互动以与他核实他是否愿意推动更改,如果是,则推送更改,否则将其删除。
是否有可能在git中的预接收挂钩中实现上述目的?
答案 0 :(得分:3)
您无法在预接收挂钩中与用户进行交互,至少一般情况下不是这样,因为用户可能在某个其他计算机上执行“ssh”,而标准输入不会发送给用户。 (您可以通过检查uid和/或用户名等来解决问题,并转出到“回调”用户的脚本。我会为您指出实验。)您可以执行所有这些检查但是。
pre-receive hook获取(在stdin上)一系列行:
<old-value> SP <new-value> SP <ref-name> LF
(引自githooks(5)
)。如果引用名称的格式为:
refs/heads/<branchname>
然后创建,删除或更新给定分支。如果<old-value>
为40 0
s,则会创建分支;如果<new-value>
为40 0
s,则会将其删除;并且它正在以其他方式更新。 (还有refs / heads / *以外的东西;请参阅git-send-email挂钩获取完整列表。)
如果正在更新分支,<old-value>
是它用来指向的提交ID,<new-value>
是允许更新时它将指向的提交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
中的所有转速,因为它们已经被发送到远程仓库,即使您要拒绝它们也是如此。
我修改(并重命名)了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
的<{1}}克隆。
要创建允许推送的等效repo,您必须创建一个名称以/some/path/to/repo.git
结尾的实际并行目录。该目录应包含一个从普通仓库复制的实际文件repo.allow.git
;目录中的其他所有内容都可以是HEAD
的符号链接:
../repo.git/<same>
cd /some/path/to
mkdir repo.allow.git
cd repo.allow.git
ln -s ../repo.git/* .
rm HEAD; cp ../repo.git/HEAD .
必须是普通文件的原因是否则HEAD
不会将此视为有效的repo(如果它是指向分支的链接,则只允许它为符号链接,这是做符号参考的“老方法”。
常规git push
失败,您可以git push
来完成它。当然,你的用户可能会养成一直这样做的习惯,避免了这个黑客的整个目的,但也许他们不会。
这一切都假设您的远程仓库是类似Unix的主机(当然,支持符号链接)。