繁体   English   中英

Git 挂钩脚本可以与存储库一起管理吗?

[英]Can Git hook scripts be managed along with the repository?

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

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

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

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

git config core.hooksPath hooks

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

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

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

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

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

对于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等效的功能。

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

如果您需要更多信息,请参阅与团队共享 Git 挂钩的两种方法

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

完全披露:我写了这个包

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

该插件将为您将内容添加到 .git 目录。

例子:

Git 构建 Hook Maven 插件

gitook-maven-插件

git-hooks-js

我想将几个答案合并为一个。 假设你在你的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!)

启用您的自定义挂钩

每个开发人员都应该在查看这些自定义挂钩后明确启用它们 在您的 README 中添加一个指令,如下所示:

通过make enable-git-hooks查看后启用自定义钩子。

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

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

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

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

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

  1. 检测和防止机密合并
  2. 强制执行正确的Git 用户配置
  3. 强制Jira 票证集成- 在拉取请求名称/提交消息中提及票证编号。

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

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

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

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

理想情况下,如果您遵循示例文件,挂钩是用 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 钩子绝对很棒,但提供它们的方式通常只会让人们远离它。

对于 Gradle 用户

我发现这些脚本对 Gradle 项目非常有用。

构建.gradle

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

gradle/安装-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

pre-commit使预提交挂钩变得容易。 没有回答OP有关管理任意git钩子的问题,但是预提交钩子可能是最常用于代码质量目的的钩子。

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

这是一篇关于只需要运行一次的脚本的文章,它将确保您不必在所有检出的存储库中单独手动设置 git 钩子,并且可以为将来检出的存储库自动工作.

https://medium.com/@paras_sipani/configuring-git-hooks-globally-for-all-current-and-future-repositories-in-1-step-af310757f19a

受到 a3765910 对 Gradle 的回答的启发,但经过修改以运行每个构建。

将以下内容添加到您的应用程序的 build.gradle(假设您已经创建了要保留在源代码管理中的 githooks/pre-commit 文件):

copy {
    from new File(rootProject.rootDir, 'githooks/pre-commit')
    into { new File(rootProject.rootDir, '.git/hooks') }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM