简体   繁体   English

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

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

We'd like to make a few basic hook scripts that we can all share -- for things like pre-formatting commit messages.我们想制作一些我们都可以共享的基本钩子脚本——例如预先格式化提交消息。 Git has hook scripts for that that are normally stored under <project>/.git/hooks/ . Git 具有通常存储在<project>/.git/hooks/下的钩子脚本。 However, those scripts are not propagated when people do a clone and they are not version controlled.但是,当人们进行克隆并且它们不受版本控制时,这些脚本不会传播。

Is there a good way to help everyone get the right hook scripts?有没有什么好方法可以帮助大家获取正确的钩子脚本? Can I just make those hook scripts point to version controlled scripts in my repo?我可以让这些钩子脚本指向我的仓库中的版本控制脚本吗?

In Git 2.9 , the configuration option core.hooksPath specifies a custom hooks directory.Git 2.9中,配置选项core.hooksPath指定了一个自定义的 hooks 目录。

Move your hooks to a hooks tracked directory in your repository.将您的钩子移动到存储库中的hooks跟踪目录。 Then, configure each instance of the repository to use the tracked hooks instead of $GIT_DIR/hooks :然后,配置存储库的每个实例以使用跟踪的hooks而不是$GIT_DIR/hooks

git config core.hooksPath hooks

In general, the path may be absolute, or relative to the directory where the hooks are run (usually the working tree root; see DESCRIPTION section of man githooks ).一般来说,路径可能是绝对的,也可能是相对于运行钩子的目录(通常是工作树根;参见man githooks的说明部分)。

Theoretically, you could create a hooks directory (or whatever name you prefer) in your project directory with all the scripts, and then symlink them in .git/hooks .从理论上讲,您可以在项目目录中创建一个包含所有脚本的hooks目录(或您喜欢的任何名称),然后在.git/hooks中对它们进行符号链接。 Of course, each person who cloned the repo would have to set up these symlinks (although you could get really fancy and have a deploy script that the cloner could run to set them up semi-automatically).当然,每个克隆 repo 的人都必须设置这些符号链接(尽管您可能会非常喜欢并拥有一个克隆器可以运行以半自动设置它们的部署脚本)。

To do the symlink on *nix, all you need to do is:要在 *nix 上进行符号链接,您需要做的就是:

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

use ln -sf if you're ready to overwrite what's in .git/hooks如果您准备好覆盖.git/hooks中的内容,请使用ln -sf

For Node.js users a simple solution is to update package.json with对于Node.js用户,一个简单的解决方案是更新package.json

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

The preinstall will run before预安装将在之前运行

npm install npm 安装

and redirects Git to look for hooks inside the .\hooks (or whatever name you choose) directory.并重定向 Git 以在.\hooks (或您选择的任何名称)目录中查找挂钩。 This directory should mimic .\.git\hooks in terms of file name (minus the .sample) and structure.这个目录应该在文件名(减去 .sample)和结构方面模仿.\.git\hooks

Imagine Maven and other build tools will have an equivalent to preinstall .想象一下Maven和其他构建工具将具有与preinstall等效的功能。

It should also work across all platforms.它也应该适用于所有平台。

If you need any more information, see Two ways to share Git hooks with your team .如果您需要更多信息,请参阅与团队共享 Git 挂钩的两种方法

If your project is a JavaScript project and you use npm as the package manager, you can use shared-git-hooks to enforce Git hooks on npm install .如果你的项目是一个 JavaScript 项目并且你使用npm作为包管理器,你可以使用shared-git-hooksnpm install上强制执行 Git 钩子。

Full disclosure: I wrote this package完全披露:我写了这个包

Most of the modern programming languages, or rather their build tools, support plugins to manage Git hooks.大多数现代编程语言,或者更确切地说是它们的构建工具,都支持插件来管理 Git 挂钩。 That means all you need to do is configure your package.json , pom.xml , etc. files, and anyone in your team will have no option but to comply unless they change the build file.这意味着您需要做的就是配置您的package.jsonpom.xml等文件,您团队中的任何人都别无选择,只能遵守,除非他们更改构建文件。

The plugin will add content to .git directory for you.该插件将为您将内容添加到 .git 目录。

Examples:例子:

Git Build Hook Maven Plugin Git 构建 Hook Maven 插件

githook-maven-plugin gitook-maven-插件

git-hooks-js git-hooks-js

I wanted to merge several answers into one.我想将几个答案合并为一个。 Assuming you are in your project/ directory:假设你在你的project/目录中:

Setup your custom hooks设置您的自定义挂钩

  1. Create .githooks directory and place your hooks in it.创建.githooks目录并将你的钩子放在其中。 (See .git/hooks for examples) (参见.git/hooks的例子)

  2. Create a .gitconfig file that points the directory ¹ :创建一个指向目录¹.gitconfig文件:

     git config -f .gitconfig core.hooksPath .githooks
  3. Create the following rule in your Makefile : ²在您的Makefile中创建以下规则: ²

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

Enable your custom hooks启用您的自定义挂钩

Every developer should explicitly enable these custom hooks after reviewing them .每个开发人员都应该在查看这些自定义挂钩后明确启用它们 Add a directive to your README, something like that:在您的 README 中添加一个指令,如下所示:

Enable custom hooks AFTER REVIEWING them by make enable-git-hooks .通过make enable-git-hooks查看后启用自定义钩子。

Use git-hooks .使用git-hooks It routes .git/hooks invoke into scripts under the project directory, githooks .它将.git/hooks调用路由到项目目录githooks下的脚本中。

There are also a lot of features to enable you to minimize copy and symlink hook all over the place.还有很多功能可以让您在各处最小化复制和符号链接挂钩。

We are using Visual Studio solutions (and thus projects) which have pre and post build events.我们正在使用具有构建前和构建后事件的 Visual Studio 解决方案(以及项目)。 I'm adding an additional project named 'GitHookDeployer'.我正在添加一个名为“GitHookDeployer”的附加项目。 The project self modifies a file in the post build event.项目在构建后事件中自行修改文件。 That file is set to copy to the build directory.该文件设置为复制到构建目录。 Thus the project is build every time and is never skipped.因此,该项目每次都构建并且永远不会被跳过。 In the build event, it also makes sure that all git hooks are in place.在构建事件中,它还确保所有 git 挂钩都到位。

Note that this is not a general solution, as some projects, of course, have nothing to build.请注意,这不是一个通用的解决方案,因为某些项目当然没有什么可构建的。

You could use a managed solution for pre-commit hook management like pre-commit .您可以使用托管解决方案进行预提交挂钩管理,例如pre-commit Or a centralized solution for server-side git-hooks like Datree.io .或者像Datree.io这样的服务器端 git-hooks 的集中式解决方案。 It has built-in policies like:它具有内置策略,例如:

  1. Detect and prevent merging of secrets .检测和防止机密合并
  2. Enforce proper Git user configuration .强制执行正确的Git 用户配置
  3. Enforce Jira ticket integration - mention ticket number in pull request name / commit message.强制Jira 票证集成- 在拉取请求名称/提交消息中提及票证编号。

It won't replace all of your hooks, but it might help your developers with the most obvious ones without the configuration hell of installing the hooks on every developers computer/repo.它不会取代您所有的钩子,但它可能会帮助您的开发人员使用最明显的钩子,而无需在每台开发人员计算机/存储库上安装钩子的配置地狱。

Disclaimer: I am one of Datrees founders免责声明:我是 Datrees 的创始人之一

You can make your hooks folder another Git repository and link it as a submodule...您可以将您的钩子文件夹设为另一个 Git 存储库并将其链接为子模块...

I guess it is worth it only if you have a lot of members and hooks changed regularly.我想只有当你有很多成员和钩子定期更换时才值得。

Ideally, hooks are written in Bash, if you follow the sample files.理想情况下,如果您遵循示例文件,挂钩是用 Bash 编写的。 But you can write it in any language available, and just make sure it has the executable flag.但是您可以用任何可用的语言编写它,并确保它具有可执行标志。

So, you can write a Python or Go code to achieve your goals, and place it under the hooks folder.因此,您可以编写 Python 或 Go 代码来实现您的目标,并将其放在 hooks 文件夹下。 It will work, but it will not be managed along with the repository.它可以工作,但不会与存储库一起管理。

Two Options两种选择

a) Multi Scripts a) 多脚本

You can code your hooks inside your help, and add a small fragment of code to hooks, to call your perfect script, like this:你可以在你的帮助中编写你的钩子,并在钩子中添加一小段代码,以调用你的完美脚本,如下所示:

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

b) Single Script b) 单一脚本

A cooler option is to add just one script to rule them all, instead of several ones.一个更酷的选择是只添加一个脚本来统治它们,而不是几个。 So, you create a hooks/mysuperhook.go file and point every hook you want to have to it.因此,您创建了一个hooks/mysuperhook.go文件并将每个您想要的钩子指向它。

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

The parameter will provide your script which hook was triggered, and you can differentiate it inside your code.该参数将为您的脚本提供触发了哪个钩子,您可以在代码中区分它。 Why?为什么? Sometimes you might want to run the same check for commit and push, for instance.例如,有时您可能希望对提交和推送运行相同的检查。

And then?接着?

Then, you might want to have further functionalities, like:然后,您可能希望拥有更多功能,例如:

  • Trigger the hook manually to check if everything is OK even prior to a commit or push.手动触发钩子以检查是否一切正常,甚至在提交或推送之前。 If you just call your script (option a or b) would do the trick.如果你只是调用你的脚本(选项 a 或 b)就可以了。
  • Trigger the hooks on CI , so you don't need to rewrite the same checks for CI.触发CI上的钩子,因此您无需为 CI 重写相同的检查。 It would be just calling the commit and push triggers, for instance.例如,它只是调用提交和推送触发器。 The same as the above should solve it.同上应该可以解决。
  • Call external tools, like a markdown validator, or a YAML validator.调用外部工具,例如 Markdown 验证器或YAML验证器。 You can make syscalls and need to handle standard output and standard error.您可以进行系统调用并需要处理标准输出和标准错误。
  • Make sure all developers have a simple way to install the hooks, so a nice script needs to be added to the repository to replace default hooks with the correct ones确保所有开发人员都有安装挂钩的简单方法,因此需要将一个漂亮的脚本添加到存储库中,以用正确的挂钩替换默认挂钩
  • Have some global helpers, like a check to block commits to develop and master branches, not having to add it to every repository.有一些全局帮助器,例如检查以阻止提交到开发和主分支,而不必将其添加到每个存储库。 You can solve it by having another repository with global scripts.您可以通过拥有另一个带有全局脚本的存储库来解决它。

Can this be simpler?这可以更简单吗?

Yes, there are several tools to help you manage Git hooks.是的,有几个工具可以帮助您管理 Git 挂钩。 Each of them is tailored to tackle the problem from a different perspective, and you might need to understand all of them to get the one that is best for you or your team.它们中的每一个都是为从不同的角度解决问题而量身定制的,您可能需要了解所有这些才能获得最适合您或您的团队的一个。 GitHooks.com offers a lot of reading about hooking, and several tools available today. GitHooks.com提供了很多关于 hooking 的阅读,以及一些当今​​可用的工具。

As of today, there are 21 projects listed there with different strategies to manage Git hooks.截至今天,这里列出了 21 个项目,它们使用不同的策略来管理 Git 挂钩。 Some only do it for a single hook, some for a specific language, and so on.有些只针对单个钩子,有些针对特定语言,等等。

One of those tools, written by me and offered for free as an open-source project, is called hooks4git .其中一个由我编写并作为开源项目免费提供的工具称为hooks4git It is written in Python (because I like it), but the idea is to handle all items listed above in a single configuration file called .hooks4git.ini , which lives inside your repository and can call any script you want to call, in any language.它是用 Python 编写的(因为我喜欢它),但想法是在一个名为.hooks4git.ini的单个配置文件中处理上面列出的所有项目,该文件位于您的存储库中,并且可以调用任何您想调用的任何脚本语。

Using Git hooks is absolutely fantastic, but the way they are offered usually only gets people away from it.使用 Git 钩子绝对很棒,但提供它们的方式通常只会让人们远离它。

For Gradle users对于 Gradle 用户

I found these scripts very useful for Gradle projects.我发现这些脚本对 Gradle 项目非常有用。

build.gradle构建.gradle

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

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

pre-commit预提交

.... your pre commit scripts goes here

pre-commit makes this easy for pre-commit hooks. pre-commit使预提交挂钩变得容易。 Doesn't answer the OP's question about managing any arbitrary git hook, but pre-commit hooks are probably the most frequently used for code quality purposes. 没有回答OP有关管理任意git钩子的问题,但是预提交钩子可能是最常用于代码质量目的的钩子。

I'm currently working on this in our codebase and I came across a library called husky which simplifies how to use and share GitHub Hooks across your team.我目前正在我们的代码库中处理这个问题,我遇到了一个名为husky的库,它简化了如何在您的团队中使用和共享 GitHub Hooks。 I highly recommend looking into that.我强烈建议调查一下。

here is an article that talks about a script that need to be run only once and will ensure that you won't have to manually set up git hooks in all your checked out repositories individually as well as would work automatically for repositories checked out in future.这是一篇关于只需要运行一次的脚本的文章,它将确保您不必在所有检出的存储库中单独手动设置 git 钩子,并且可以为将来检出的存储库自动工作.

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

Inspired by a3765910's answer for Gradle but modified to run every build.受到 a3765910 对 Gradle 的回答的启发,但经过修改以运行每个构建。

Add the following to your app's build.gradle (assuming you already created the githooks/pre-commit file you want to keep in source control):将以下内容添加到您的应用程序的 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