Git remote/shared pre-commit钩子

m0rkklqb  于 2023-03-21  发布在  Git
关注(0)|答案(8)|浏览(167)

有了一个官方仓库作为远程仓库,多个本地仓库从它克隆,可以在主仓库上编写一个预提交钩子,并在它的所有克隆上强制执行吗?

vxf3dgd4

vxf3dgd41#

我不这么认为,因为钩子不是克隆的。
如果钩子脚本本身是版本化的,然后链接到克隆服务器中的(符号链接)(假设它们的操作系统支持该链接功能),则可能是这样。
或者,如果钩子是用于创建克隆的git模板目录的一部分(这只能确保它们存在于克隆存储库中,但不能保证它们实际上被使用和执行)。
但我不认为有任何“中心”的方式来强制提交。
正如Jefromi在评论中更清楚地解释的那样(强调我的):
我认为这真的违背了git仓库的想法,让强制钩子与仓库一起分发。

我的克隆是我的仓库.我应该可以在上面使用git,包括选择是否运行钩子。

(And从安全的Angular 来看,这真的有点可怕-没有人应该有能力在我运行某些git命令时强制我执行某些脚本。
我同意这一评论,并且只看到了在给定的专门仓库中强制执行本地应用规则的方法。
例如,你不会直接推送到中央仓库,而是会先推送到QA仓库,只有当它遵循某些规则时,它才会接受你的提交。如果它接受了,那么QA仓库会将你的提交推送到中央仓库。
另一个例子直接来自我刚才提到的“Serverless Continuous Integration with Git”,一种在将它们推到任何地方之前强制执行 * 本地 * 私有构建的方法。

pb3skfrl

pb3skfrl2#

你不能在人们的本地仓库上强制预提交钩子,但在你的中央仓库中,你仍然可以运行预接收钩子。

例如,我需要确保提交消息遵守某些规则(用于trac集成等),所以我使用了以下pre-receive钩子,它检查每个被推送到中央存储库的提交消息,如果它不是welformed,它将拒绝推送。

#!/bin/sh
while read rev_old rev_new ref
do
    MALFORMED="$(git rev-list --oneline $rev_old..$rev_new | egrep -v '#[0-9]+' |  awk '{print $1}' )"
    if [ x"$MALFORMED" != x ]
    then
        echo Invallid commit message on $MALFORMED
        exit 1
    fi
done

更多信息见f.ex https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

xjreopfe

xjreopfe3#

两个选项:

1.使用哈士奇

如果你正在编写JavaScript,最好的方法是使用Husky。Husky有一个postInstall脚本,可以设置和管理你的githooks。然后你可以在package.json或husky dotfile中配置precommit和prepush脚本。

你可以使用它来运行任意脚本。我通常使用yarn lintyarn test prepush。

2.在git.config中设置core/hooksPath,然后在repo中包含/hooks

如果您没有使用JavaScript,或者您无法使用Husky,您可以将提交钩子克隆到开发人员机器上并将其签入到repo中,但您不能强制开发人员运行它们。

要签入你的钩子,在你的仓库中创建一个hooks目录。然后把你的钩子放在那里,而不是通常的.git/hooks目录。这是你可以强制执行的部分。
另一部分取决于开发者的意愿。要将hooks文件夹设置为hooksPath,每个开发者必须运行:
git config core.hooksPath hooks
现在hooks文件夹中的所有钩子都将按照您所期望的方式运行。

ws51t4hk

ws51t4hk4#

一个预提交钩子是否可以在主存储库上编写脚本,并在它的所有克隆上强制执行?
githooks(5)开始:

**pre-commit**
      This hook is invoked by git commit, and can be bypassed with
      --no-verify option.

由于钩子可以很容易地被绕过,看来你的问题的答案是“不”。
此外,由于.git/hooks目录没有被克隆,因此似乎没有将其推送到客户端的机制。

laximzn5

laximzn55#

这里有非常非常古老的答案。这在今天绝对是可能的。
从Git 2.9左右开始,配置core.hooksPath可用。根据git文档:
core.hooksPath
默认情况下,Git会在$GIT_DIR/hooks目录中查找你的钩子。将其设置为不同的路径,例如/etc/git/hooks,Git会尝试在该目录中查找你的钩子,例如/etc/git/hooks/pre-receive而不是$GIT_DIR/hooks/pre-receive
路径可以是绝对的也可以是相对的。相对路径是相对于钩子运行的目录的(参见githooks[5]的“描述”部分)。
如果你想集中配置你的Git钩子,而不是在每个仓库的基础上配置它们,或者作为一个更灵活和集中的替代方案,你已经改变了默认钩子的init.templateDir,这个配置变量是有用的。
这意味着你可以在客户端机器之间共享Git钩子(可能使用项目中的非.git文件夹,或者使用本地克隆的专用Git存储库,或者使用OneDrive或Dropbox等同步软件),只需将core.hooksPath配置设置为该(共享)文件夹即可。

l7wslrjt

l7wslrjt6#

假设你的git repo中有一个源代码,并且有一个与之关联的构建系统,你可以配置构建系统来设置pre-commit钩子,即通过移动或链接一个版本化的pre-commit钩子。
我还没有试过这个,我是在谷歌寻找更好的解决方案的时候来这里的。

pvabu6sv

pvabu6sv7#

这不是完全自动的,但你可以在hooks/目录中添加一个仓库的钩子脚本,然后让开发人员在克隆仓库后对钩子脚本进行一次符号链接:

ln -s ../../hooks/pre-commit.sh .git/hooks/pre-commit

在项目README中编写文档可能会很好地工作。

qnzebej0

qnzebej08#

我创建一个新文件:pre-commit-hook.sh

#!/usr/bin/env bash
CHANGES=$(git whatchanged ..origin)

if [ ! -z "${CHANGES}" ]; then
    echo "There are changes in remote repository. Please pull from remote branch first."
    exit 1;
fi

exit 0;

这就是我对Git的承诺:

bash pre-commit-hook.sh && git commit -m "<Commit message>"

相关问题