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


336

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

有没有一种好的方法可以帮助每个人获得正确的钩子脚本?我可以仅使这些挂钩脚本指向我的存储库中的版本控制脚本吗?


5
一个好问题。我只希望有一个更好的答案(没有@mipadi的投诉,我只是希望git有一种更自动的方式来做到这一点-即使仅在git clone中指定了一个选项。)
lindes

我同意,@ lindes!但是,也许有意限制这种钩子共享吗?我想对于Windows用户来说事情会变得混乱。
kristianlm 2011年

@kristianlm:出于各种原因,有时可能会很乱……有时也很可能把它放在那里。我只是希望有一些选择或某些东西可以复制钩子。我想我只需要在某个时候签出git-core代码,然后打个补丁即可。:)(或希望其他人可以...或忍受
mipadi

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

Answers:


143

从理论上讲,您可以hooks使用所有脚本在项目目录中创建目录(或您喜欢的任何名称),然后在中将它们符号链接.git/hooks。当然,每个克隆该存储库的人都必须设置这些符号链接(尽管您可能真的很喜欢,并且拥有一个部署脚本,克隆程序可以运行该脚本来半自动设置它们)。

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

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

使用ln -sf,如果你准备覆盖什么在.git/hooks


38
这是不平凡的,所以我包括一个链接就如何正确符号链接:stackoverflow.com/questions/4592838/...
大卫吨

17
git 2.9版现在具有一个config选项,core.hooksPath用于设置.git之外的文件以链接到hooks文件夹。
亚伦·拉比诺维兹

215

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

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

git config core.hooksPath hooks

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


15
...以及指向的hooks目录可以是单独的hooks存储库;)
RenéLink 2016年

10
好了,执行git clone时会自动设置此配置参数吗?
2016年

4
通常,您要克隆的存储库无法设置git config变量。我认为这是为了防止执行任意代码。git config通过挂钩,提交消息上的用户名和其他重要功能控制代码的执行。
Max Shenfield

1
如果团队中的某人对另一个分支进行git checkout怎么办?他们必须在每个分支中都包含它
。.– jokerster

1
确实如此。另一方面,如果在较新的提交中更新挂钩,则克隆的回购协议将在基于该提交之上构建的分支上工作时自动获取。两种方式都有其优点和缺点。
fabb

15

如果您的项目是JavaScript项目,并且npm用作包管理器,则可以使用shared-git-hooks在上实施githooks npm install


5
现在我知道是谁在将这些废话加进来.git/hooks
Givenkoa

警告-不支持Windows(除非它在git bash中以管理员身份运行)。简单的解决方案是在package.json中添加“ preinstall”:“ git config core.hooksPath hooks”作为脚本。即,其中的钩子是包含您的git脚本的文件夹。
Shane Gannon

8

对于的NodeJS用户一个简单的解决方案是更新的package.json

{
  "name": "name",
  "version": "0.0.1",
  ......
  "scripts": {
    "preinstall": "git config core.hooksPath hooks", 

预安装将前运行

npm安装

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

想象一下,Maven和其他构建工具将具有等同于预安装的功能

它也应该在所有平台上工作。

如果您需要更多信息,请参见https://www.viget.com/articles/two-ways-to-share-git-hooks-with-your-team/


5

git-hooks怎么样,它将.git/hooks调用路由到项目目录下的脚本中githooks

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


5

大多数现代编程语言,或者更确切地说,它们的构建工具,都支持管理git hook的插件。这意味着您只需要配置package.json,pom.xml等,团队中的任何人就别无选择,除非他们更改构建文件。该插件将为您添加内容到.git目录。

例子:

https://github.com/rudikershaw/git-build-hook

https://github.com/olukyrich/githook-maven-plugin

https://www.npmjs.com/package/git-hooks


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

3

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

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


2

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

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

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

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


1

您可以将hooks文件夹设置为另一个git存储库,并将其作为子模块进行链接...仅当您定期更改许多成员和hook时,我才认为值得。


1

理想情况下,如果遵循示例文件,则钩子将以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检查,例如,只需调用commit和push触发器即可。与上述相同应解决。
  • 调用外部工具,例如降价验证器或YAML验证器。您可以进行系统调用,并且需要处理STDOUT和STDERR。
  • 确保所有开发人员都有安装钩子的简单方法,因此需要向存储库中添加漂亮的脚本,以将正确的钩子替换为默认钩子
  • 有一些全局助手,例如检查阻止开发和掌握分支的提交,而不必将其添加到每个存储库中。您可以通过使用具有全局脚本的另一个存储库来解决它。

这可以更简单吗?

是的,有几种工具可以帮助您管理git-hook。他们每个人都是量身定制的,以从不同的角度解决问题,您可能需要了解所有这些因素,才能找到最适合您或您的团队的东西。GitHooks.com提供了大量有关钩子的信息,并且提供了当今可用的几种工具。

截至今天,这里列出了21个项目,这些项目采用不同的策略来管理git hooks。有些仅针对单个钩子执行此操作,某些仅针对特定语言执行此操作,依此类推。

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

使用git hooks绝对是太棒了,但是提供它们的方法通常只会使人们远离它。


不久前,我发布了一个非常短的版本,并与主持人达成共识,这在其中带来了解释,并简要链接到我自己编写的工具,我认为这可能会对其他开发人员有所帮助。
Lovato

1

对于gradle用户

我发现这些脚本对于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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.