Git挂钩拒绝包含子模块更新的推送?

时间:2014-09-09 14:08:22

标签: git git-submodules githooks

我使用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中被推送的子模块提交吗?

2 个答案:

答案 0 :(得分:1)

您的问题在于您尝试阅读OLDREVNEWREF的方式。

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"不在第二个输出中,也不是第一个命令返回的任何子模块路径。