git 钩子预推 bash 脚本验证标签

git hook pre-push bash script validate tag

我正在尝试使用预推 git 挂钩验证 git 标签,但每当我执行 git push origin <tag-name> 时,它都会将前一个标签作为 [=31] 的最新标签=].

重现问题:

Step 1. git commit 
step 2. git tag V1.0.0-US123-major
step 3. git push origin V1.0.0-US123-major

所以当第 3 步执行时,预推脚本应该使用 "V1.0.0-US123-major" 标签并验证下面的正则表达式。如果标签与正则表达式匹配,那么它是一个有效的标签,否则中止 git push.

#!/bin/sh
read_tag="$(git describe --abbrev=0 --tags)"
if [[ $read_tag =~ (^v[0-9]{1}.[0-9]{1}.[0-9]{1}-[a-zA-Z]+-[a-zA-Z]+$) ]]; then
    echo "matched"
    
else
    echo "not matched"
    exit 1
fi

我的期望是当我使用 git push origin 2.2.2.2 时,预推脚本不会 return exit1 而是接受标签并推送到不正确的原点。

git push origin 2.2.2
latest tag: v5.5.5-abcd-tues
matched

有人可以帮我解决这个问题吗?

您的 pre-push 挂钩正在检查当前修订版,而不是您推送的标签,因为如果您不另行指定,git describe 会描述 HEAD

当您使用 pre-push 挂钩时,被推送的引用将通过标准输入传递。假设您要检查的是 remote 引用的名称(即最终将出现在服务器上的引用),那么它可能看起来像这样(使用 POSIX语法):

#!/bin/sh

set -e

while read lref new rref old
do
    case $rref in
        refs/tags/*)
            if echo "$rref" | \
                grep -qsE '(^refs/tags/v[0-9]{1}.[0-9]{1}.[0-9]{1}-[a-zA-Z]+-[a-zA-Z]+$)'
            then
                echo "matched"
            else
                echo "not matched"
                exit 1
            fi;;
        *)
            ;;
    esac
done

请注意,虽然 pre-push 挂钩可以帮助开发人员做出正确的选择并避免错误,但它并不是一个有效的控件,因为它可以被轻易绕过。如果您需要限制推送到服务器的内容,您需要使用 pre-receive 挂钩、您的服务器实现或 CI 系统来实现。有关更多信息,请参阅 the relevant Git FAQ entry