如何检查 git 提交是否在消息中包含字符串模式?

How to check that git commits contain string pattern in message?

我有一个包含一些项目的 GitLab 存储库。我想检查提交消息是否包含正则表达式字符串模式(例如,'[0-9]{3}'),以供想要推送他对项目的提交的人使用。如果用户的提交消息中没有字符串模式,则该用户的 return 消息 "Your commit's message doesn't contain necessary string pattern"。

我知道有 git 钩子,我可以在这里编写自己的钩子:/var/opt/gitlab/git-data/repositories/root/awesome.git/custom_hooks/pre-receive 但是我如何检索用户的提交消息?

在 pre-receive 或更新挂钩中,您在标准输入上或作为参数给出了一个 引用名称 旧值 和参考的 新值 。更新挂钩获取一个引用作为参数。您可以根据这三个参数对单个引用更新做出单一决定:允许它或阻止它。 pre-receive 挂钩在其标准输入上获取 all 建议的更新,每行一个,您必须阅读标准输入的 all在做出你的一个决定之前:允许所有建议的更新传递到下一步——包括 运行 更新挂钩,一次一个名称——或者拒绝整个更新。

在所有情况下,每个引用都使用其完整的 spelled-out 格式。请务必全部使用,以免将 tag Xrefs/tags/X 误认为是命名 分支X。同样,不要将分支名称 refs/heads/experiment/masterrefs/heads/master 混淆,如果您简单地剥离(即包括)最后的 / 中的所有内容,就会发生这种情况。您甚至可能会收到更新既不是分支名称 也不是 标签名称的引用的请求,例如 refs/replace/ name-space 项目,或 refs/notes/commits.

类似地,旧值和新值是两个完整的 Git 哈希 ID,除了恰好一个——永远不会是两个——可能是特殊的 all-zeros "null hash"。 null 散列表示正在创建引用(旧值 null,新值 non-null)或销毁(旧值 non-null,新值 null)。

查看提交

如果您希望查看所有传入提交的消息,则必须遍历 $oldhash..$newhash 中的每个提交,但您必须以不同方式处理 "reference being created" 或 "reference being destroyed"。创建引用时,有时无法知道如果有任何 由于那个新引用而进入了哪个提交。例如,考虑您的 pre-receive 钩子得到:

的情况
012...789 aaa...aaa refs/heads/br1
345...eee 321...def refs/heads/br2
000...000 999...999 refs/tags/v2.1

现在,正在创建 refs/tags/v2.1(其旧值为 all-zeros)。它的新值是 999...,大概是一个带注释的标签 object 或一个提交 object。但是,如果 999... 到达 parent 是 888... 888... 之前不在存储库中的提交怎么办?那么新创建的标签可能就是提交的来源888...。另一方面,两个分支名称 br1br2 也正在更改。如果其中之一也达到 888... 怎么办? (例如,也许那是 aaa... 的盛大 parent 提交。)

最接近 "commits introduced by new reference" 的方法是使用 git rev-list <hash> --not --all 获取哈希 ID 可访问的提交列表,这些提交尚未从所有现有引用中访问。这会将新提交 888... 计为可从标签访问,即使它也 将是 可从 br1 访问(前提是您允许更新到 br1当然)。

对于你的情况,这可能没问题:如果你拒绝在 br1 上有错误消息的提交,你也可以拒绝在 v1.2 上有错误消息的提交,这意味着你拒绝了两次提交,但那又怎样?或者它可能 not 没问题,在这种情况下,您必须决定您希望如何处理它。请记住,您的选择是在 pre-receive 挂钩中读取 所有 更新,并允许它们全部继续或全部拒绝;或在更新挂钩中检查每个更新一次,并允许该更新继续,或拒绝它。在 pre-receive 挂钩中,由于您拥有所有更新的全局视图,因此您可以编写花哨的逻辑。在更新挂钩中,您的视野狭窄,您不能编写花哨的逻辑:您必须保持简单。各有优缺点。

无论如何,一旦有了更新,您就可以判断哪些提交在更新后可以访问,哪些还无法访问:

git rev-list $newvalue ^$oldvalue | ...

并且您可以根据不再可访问的旧参考值判断哪些提交是可访问的:

git rev-list $oldvalue ^$newvalue | ...

(后者是通过 force-push 删除 的提交)。在代码的 ... 部分,您可以读取每个提交哈希并对其进行任何您喜欢的操作,例如:

... | while read hash; do
    if git log --format=%B $hash | grep "$expr" >/dev/null; then
        # grep found a pattern in the body printed by %B
    else
        # grep did not find the pattern
    fi
done