【问题标题】:Can Git hook scripts be managed along with the repository?Git 钩子脚本可以与存储库一起管理吗?
【发布时间】:2020-12-29 21:54:25
【问题描述】:

我们想制作一些我们都可以共享的基本钩子脚本——例如预先格式化提交消息。 Git 具有通常存储在<project>/.git/hooks/ 下的钩子脚本。但是,当人们进行克隆并且它们不受版本控制时,这些脚本不会传播。

有没有什么好方法可以帮助大家获得正确的钩子脚本?我可以让这些钩子脚本指向我的仓库中的版本控制脚本吗?

【问题讨论】:

  • 一个好问题。我只希望有一个更好的答案(没有对@mipadi 的抱怨,我只希望 git 有办法以更自动的方式做到这一点——即使只为 git clone 指定了一个选项。)
  • 我同意,@lindes!但也许是有意限制这种挂钩的共享?我想,对于 Windows 用户来说,事情会变得一团糟。
  • @kristianlm:有各种各样的原因,它有时可能会很混乱......而且有时它很高兴在那里。我只是希望有一些选项或可以复制钩子的东西。我想我只需要在某个时候检查一下 git-core 代码,然后打一个补丁。 :) (或者希望其他人这样做......或者使用mipadi's answer 中的解决方法,或者其他什么。)
  • pre-commit 使预提交挂钩变得容易。没有回答 OP 关于管理任意 git 钩子的问题,但预提交钩子可能是最常用于代码质量目的的钩子。

标签: git githooks


【解决方案1】:

理论上,您可以在项目目录中创建一个包含所有脚本的hooks 目录(或您喜欢的任何名称),然后将它们符号链接到.git/hooks。当然,每个克隆 repo 的人都必须设置这些符号链接(尽管您可能会非常喜欢并拥有一个克隆器可以运行的部署脚本来半自动地设置它们)。

要在 *nix 上进行符号链接,您需要做的就是:

root="$(pwd)"
ln -s "$root/hooks" "$root/.git/hooks"

如果您准备好覆盖 .git/hooks 中的内容,请使用 ln -sf

【讨论】:

  • 这很重要,所以我提供了一个关于如何正确符号链接的链接:stackoverflow.com/questions/4592838/…
  • git 2.9 版现在有一个配置选项core.hooksPath 可以在 .git 之外设置一个文件以链接到 hooks 文件夹。
【解决方案2】:

使用git-hooks。它将.git/hooks 调用路由到项目目录githooks 下的脚本中。

还有很多功能可以让您在各处最小化复制和符号链接挂钩。

【讨论】:

  • 这实际上是难以理解的。您是否使用过机器翻译(例如,Google Translate)来回答这个问题?为什么要投票?
【解决方案3】:

如果您的项目是 JavaScript 项目并且您使用 npm 作为包管理器,则可以使用 shared-git-hooksnpm install 强制执行 Git 挂钩。

完全披露:我写了这个包

【讨论】:

  • 警告 - 不支持 Windows(除非它在 ​​git bash 中以管理员身份运行)。简单的解决方案是在 package.json 中添加“preinstall”:“git config core.hooksPath hooks”作为脚本。即 hooks 是一个包含你的 git 脚本的文件夹。
【解决方案4】:

Git 2.9 中, 配置选项core.hooksPath 指定一个自定义挂钩目录。

将您的挂钩移动到您的存储库中的 hooks 跟踪目录。然后,将存储库的每个实例配置为使用跟踪的hooks 而不是$GIT_DIR/hooks

git config core.hooksPath hooks

一般来说,路径可以是绝对的,也可以是相对于运行钩子的目录(通常是工作树根;参见 man githooks 的说明部分)。

【讨论】:

  • ... 和指向的 hooks 目录可以是单独的 hooks 存储库 ;)
  • 那么,这个配置参数是在你执行 git clone 时自动设置的吗?
  • 作为一条规则,你正在克隆的存储库不能设置 git config 变量。我认为这是为了防止执行任意代码。 git config 通过钩子、提交消息上的用户名和其他重要功能控制代码的执行。
  • 如果团队中有人对另一个分支进行 git checkout 怎么办?他们必须将它包含在每个分支中..
  • 确实如此。另一方面,如果您在较新的提交中更新挂钩,克隆的 repos 将在基于该提交构建的分支上工作时自动获取它们。两种方式都有其优点和缺点。
【解决方案5】:

我们正在使用具有构建前和构建后事件的 Visual Studio 解决方案(以及项目)。我正在添加一个名为“GitHookDeployer”的附加项目。项目在构建后事件中自行修改文件。该文件设置为复制到构建目录。因此,该项目每次都构建并且永远不会被跳过。在构建事件中,它还确保所有 git 钩子都到位。

请注意,这不是一个通用的解决方案,因为有些项目当然没有什么可构建的。

【讨论】:

    【解决方案6】:

    大多数现代编程语言,或者更确切地说是它们的构建工具,都支持插件来管理 Git 挂钩。这意味着您需要做的就是配置您的 package.jsonpom.xml 等文件,您团队中的任何人都别无选择,只能遵守,除非他们更改构建文件。

    插件会为你添加内容到 .git 目录。

    示例:

    Git Build Hook Maven Plugin

    githook-maven-plugin

    git-hooks-js

    【讨论】:

    • 我试图以一种通用的方式实现这一点,以便在我的项目中使用,所以我编写了这个工具:pypi.org/project/hooks4git
    【解决方案7】:

    您可以将您的 hooks 文件夹设为另一个 Git 存储库并将其链接为子模块...

    我想只有当你有很多成员和钩子定期更换时才值得。

    【讨论】:

      【解决方案8】:

      您可以使用托管解决方案进行预提交挂钩管理,例如 pre-commit。 或者像 Datree.io 这样的服务器端 git-hooks 的集中式解决方案。 它具有以下内置策略:

      1. 检测并阻止merging of secrets
      2. 强制执行正确的Git user configuration
      3. 强制执行Jira ticket integration - 在拉取请求名称/提交消息中提及票号。

      它不会取代你所有的钩子,但它可能会帮助你的开发人员使用最明显的钩子,而无需在每个钩子上安装钩子的配置地狱。 开发者计算机/repo。

      免责声明:我是 Datrees 的创始人之一

      【讨论】:

        【解决方案9】:

        如果您遵循示例文件,理想情况下,挂钩是用 Bash 编写的。但是你可以用任何可用的语言编写它,并确保它具有可执行标志。

        因此,您可以编写 Python 或 Go 代码来实现您的目标,并将其放在 hooks 文件夹下。它可以工作,但不会与存储库一起管理。

        两种选择

        a) 多脚本

        您可以在帮助中编写您的钩子,并在钩子中添加一小段代码,以调用您的完美脚本,如下所示:

        $ cat .git/hooks/pre-commit
        #!/bin/bash
        ../../hooks/myprecommit.js
        

        b) 单一脚本

        一个更酷的选择是只添加一个脚本来统治它们,而不是几个。因此,您创建了一个 hooks/mysuperhook.go 文件并将每个您想要的挂钩指向它。

        $ cat .git/hooks/pre-commit
        #!/bin/bash
        ../../hooks/mysuperhook.go $(basename $0)
        

        该参数将提供您的脚本触发了哪个钩子,您可以在代码中区分它。为什么?例如,有时您可能希望对提交和推送运行相同的检查。

        然后呢?

        然后,您可能希望拥有更多功能,例如:

        • 手动触发挂钩以检查是否一切正常,甚至在提交或推送之前。如果你只是调用你的脚本(选项 a 或 b)就可以了。
        • 触发CI 上的挂钩,因此您无需为CI 重写相同的检查。例如,它只是调用提交和推送触发器。和上面一样应该可以解决。
        • 调用外部工具,例如 Markdown 验证器或 YAML 验证器。您可以进行系统调用并需要处理标准输出和标准错误。
        • 确保所有开发人员都有安装挂钩的简单方法,因此需要向存储库添加一个漂亮的脚本,以用正确的挂钩替换默认挂钩
        • 有一些全局帮助程序,例如检查以阻止提交以开发和掌握分支,而不必将其添加到每个存储库。您可以通过使用另一个包含全局脚本的存储库来解决它。

        这可以更简单吗?

        是的,有多种工具可以帮助您管理 Git 挂钩。它们中的每一个都是为从不同的角度解决问题而量身定制的,您可能需要了解所有这些才能获得最适合您或您的团队的一个。 GitHooks.com 提供了很多关于 hooking 的阅读,以及一些当今​​可用的工具。

        截至今天,这里列出了 21 个项目,它们采用不同的策略来管理 Git 挂钩。有些只针对单个钩子,有些针对特定语言,等等。

        其中一个工具由我编写并作为开源项目免费提供,名为hooks4git。它是用 Python 编写的(因为我喜欢它),但想法是在一个名为 .hooks4git.ini 的单个配置文件中处理上面列出的所有项目,该文件位于您的存储库中并且可以调用任何脚本你想打电话,用任何语言。

        使用 Git 钩子绝对很棒,但提供它们的方式通常只会让人们远离它。

        【讨论】:

        • 前段时间我发布了一个非常短的版本,根据与版主的约定,这在其中带来了解释,以及一个我自己编写的工具的简短链接,我认为这可能会帮助其他开发人员。
        【解决方案10】:

        对于Node.js 用户,一个简单的解决方案是使用

        更新 package.json
        {
          "name": "name",
          "version": "0.0.1",
          ......
          "scripts": {
            "preinstall": "git config core.hooksPath hooks",
        

        预安装会在之前运行

        npm 安装

        并重定向 Git 以在 .\hooks(或您选择的任何名称)目录中查找挂钩。这个目录应该在文件名(减去 .sample)和结构方面模仿 .\.git\hooks

        想象一下Maven 和其他构建工具将有一个相当于preinstall

        它也应该适用于所有平台。

        如果您需要更多信息,请联系 Two ways to share Git hooks with your team

        【讨论】:

        【解决方案11】:

        对于 Gradle 用户

        我发现these scripts 对于 Gradle 项目非常有用。

        build.gradle

        apply from: rootProject.file('gradle/install-git-hooks.gradle')

        gradle/install-git-hooks.gradle

        tasks.create(name: 'gitExecutableHooks') {
            doLast {
                Runtime.getRuntime().exec("chmod -R +x .git/hooks/");
            }
        }
        task installGitHooks(type: Copy) {
            from new File(rootProject.rootDir, 'pre-commit')
            into { new File(rootProject.rootDir, '.git/hooks') }
        }
        gitExecutableHooks.dependsOn installGitHooks
        clean.dependsOn gitExecutableHooks
        

        预提交

        .... your pre commit scripts goes here
        

        【讨论】:

        • 文件没有从自定义目录复制到 .git/hooks 目录。连同上面的代码,如果我们添加这行代码,它将无缝地工作。 fileMode 0777
        【解决方案12】:

        我想将几个答案合并为一个。假设您在 project/ 目录中:

        设置您的自定义挂钩

        1. 创建.githooks 目录并将你的钩子放入其中。 (示例见.git/hooks

        2. 创建一个指向¹目录的.gitconfig文件:

          git config -f .gitconfig core.hooksPath .githooks
          
        3. 在您的Makefile 中创建以下规则:²

          enable-git-hooks:
              git config --local include.path ../.gitconfig
              $(warning REMEMBER, YOU MUST HAVE REVIEWED THE CUSTOM HOOKS!)
          

        启用您的自定义挂钩

        每个开发者都应该explicitly enable these custom hooks after reviewing them。在你的 README 中添加一个指令,类似这样:

        make enable-git-hooks 审核后启用自定义挂钩。

        【讨论】:

          【解决方案13】:

          我目前正在我们的代码库中处理这个问题,我遇到了一个名为 husky 的库,它简化了如何在您的团队中使用和共享 GitHub Hooks。我强烈建议调查一下。

          【讨论】:

            猜你喜欢
            • 2013-12-06
            • 2010-10-28
            • 2011-01-04
            • 1970-01-01
            • 2013-03-03
            • 1970-01-01
            • 1970-01-01
            • 2022-08-03
            相关资源
            最近更新 更多