我使用gitosis来托管我的GIT存储库。
我想阻止管理员以外的用户(由提交者的电子邮件识别)将更新推送到子模块。
我试着看看是否可以通过预接收挂钩读取子模块更改列表,但由于它是一个裸存储库,它无法读取.gitmodules。
#!/bin/bash
OLDREV=$1
NEWREV=$2
unset GIT_DIR
unset GIT_WORKING_TREE
SUBS=$(git show $NEWREV:.gitmodules | sed -n "s/^.*git@repo://p")
for submod in SUBS
do
echo $submod
done
exit 1
但我明白了:
remote: fatal: Path '.gitmodules' does not exist (neither on disk nor in the index).
你知道我怎么能读取在pre-receive hook中被推送的子模块提交吗?
答案 0 :(得分:1)
您的问题在于您尝试阅读OLDREV
和NEWREF
的方式。
Githooks没有像你期望的那样获得他们的论点,他们被写入stdin,这实际上意味着他们被管道输入。
要正确阅读它们,您必须执行以下操作:
while read OLDREF NEWREF REFNAME
do
# Work with the references ...
done
pre-push.example
挂钩 - 您可以在每个git存储库中找到它 - 给人留下了良好的印象。
答案 1 :(得分:1)
要自己滚动,您可以挂钩预先接收或更新。 pre-receive通过STDIN一次获取所有引用一行,更新通过args $ 1 = ref获得refs,$ 2 = old,$ 3 = new。
.gitmodules文件只有在有人添加子模块,删除子模块或将远程路径或名称更改为子模块(而不是SHA指向的现有子模块,这更常见)时才会被修改。
对现有子模块中签出的SHA的更改将在.gitmodules路径条目中指定的路径上表示为不同的SHA。
所以,如果您要git submodule add ../sub1 my_submodule
,则会对.gitmodules
cat .gitmodules
[submodule" my_submodule"]
path = my_submodule
url = ../ sub1
但是你也可以通过git cat-file -p HEAD^{tree}
注意特殊" 160000"文件模式,表示子模块
160000提交a07f4c5277d2b3e53e95b19156610c6dc6c28e49 my_submodule
假设您的repo中已存在.gitmodules文件,那么您不仅要阻止对其进行更改,还要阻止对其中列出的任何子模块进行更改。
在你的钩子里
这将打印出当前跟踪的所有子模块的路径
git cat-file -p ${old}:.gitmodules | grep path | awk -F= '{print $NF}'
这将打印出从旧参考文件更改为新参考文件的所有文件的路径
git diff --name-only ${old}..${new}
使用您喜欢的任何技术来验证" .gitmodules"不在第二个输出中,也不是第一个命令返回的任何子模块路径。