如何测试我的预接收挂钩?

时间:2017-11-14 13:35:25

标签: git githooks

我需要创建一个预接收挂钩,拒绝任何来自任何非主服务器的客户端的推送,所以我写了这个脚本:

     #!/bin/bash

    refname="$0"
    oldrev="$1"
    newrev="$2"

    alowed_branch='master'
    current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

    if [ $alowed_branch = $current_branch ]
    then
      echo "you are pushing to master branch"
      exit 0
    else
      echo Branch $current_branch is Locked.
     exit 1
    fi

现在我不知道如何测试它......

在预先提交时进行测试'挂钩我当地的git repo我得到了我想要的东西:

enter image description here

但是当尝试将其作为预推或预接收挂钩进行测试时,它不会产生任何影响,我可以在不受干扰的情况下进行推送。

有没有办法在GitHub上测试它?

1 个答案:

答案 0 :(得分:2)

测试挂钩,特别是预接收挂钩很困难:它们在不寻常的环境中运行。几乎没有很好的方法来测试它们(主要的好方法是一个或两个牺牲的存储库)。

这里有许多相互交织的问题:

refname="$0"

无论如何都是错误的,就像在shell脚本中一样,$0引用脚本本身的名称

current_branch=$(refname) 

您在编辑中删除的内容也是错误的:它尝试运行命令refname。所以你替换它很好,但是:

current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

这是一个巧妙的错误:如果您当前的分支名为fixes/bug-123,它会将current_branch设置为bug-123,而不是fixes/bug-123

要将当前分支名称作为符号引用减去refs/heads/部分,请使用:

current_branch=$(git symbolic-ref --short HEAD) || exit 1

--short指示git symbolic-ref省略refs/heads/部分,|| exit 1指示 shell 退出(失败状态) git symbolic-ref本身失败了,它可以:如果你有一个"分离的HEAD",HEAD 不是一个符号引用,Git会抱怨这个并且current_branch将设置为空字符串。

现在,有了这些,你提到:

  

...尝试将其作为推前或预接收挂钩进行测试...

作为预推钩,$1$2(存储在oldrevnewrev中)实际上会设置为远程的名称和网址!旧的和新的修订ID以及旧的和新的引用名称将作为其标准输入传递给该挂钩。这一切都发生在客户端,在连接到其他Git(远程)之后但在发送任何内容之前。 (See the section on pre-push hooks in the githooks documentation.)

作为预接收挂钩,$1$2 根本不会设置为任何(这是正常的,因为您永远不会使用变量)。 当前分支将是远程上另一个Git中的当前分支。预接收挂钩(如预推钩)必须读取其标准输入,一次一行,检查该行上提供的每组参数。如果钩子以非零返回退出,则整个推送被拒绝(从服务器端)。

在预推或预接收挂钩中检查参考名称时,请务必检查整个参考:传入参考(在任何挂钩中)或传出参考(在预推中) hook)可以引用标记,例如refs/tags/v1.2中的标记,或者名称包含斜杠的分支,如refs/heads/feature/tall中所示。除了名字的最后一部分之外,不要砍掉除了前两部分之外的所有部分,而不是看它们。并且,在任何一个钩子中,当前分支名称通常完全不相关:运行git push的人指定在命令行上推送的引用:

git push origin \
  refs/heads/master:refs/for/master \
  refs/tags/v1.2:refs/tags/v1.2 \
  refs/notes/commits:refs/notes/commits \
  refs/peculiar-ref:refs/even-stranger/master
例如

。这些都不会进入目标上的分支;只有一个来自来源的分支。

(请注意,钩子可以用任何可以在安装了特定Git的机器上运行的语言编写。他们不会 成为bash / sh脚本 - 但是如果你有Git你必须有一个shell,因为Git的部分是用shell编写的。总是要注意硬编码的路径:例如,在某些系统上,bash可能位于/usr/local/bin/bash而不是/bin/bash。)< / p>