>> >> >> Reference << << << <<<<<<Ref>>>>>>
Hooks
Modified: 2025-12-31 | Author:ljf12825

Git Hooks是Git在特定重要动作(如提交、推送、接收等)发生时自动运行的脚本。它们是一种内置的功能,允许自定义和自动化Git的工作流程
可以把Git Hooks想象成事件监听器。当Git执行到某个关键节点时(比如pre-commitpost-merge),它会检查对应的钩子脚本是否存在。如果存在并且有执行权限,Git就会运行这个脚本

每个Git仓库都有一个内置的钩子目录:.git/hooks/。在这个目录下,会看到许多示例脚本(以.sample结尾),它们展示了各种钩子的用法
不能直接创建任意名称的全新钩子(比如pre-deploy)。Git的钩子系统是固定事件的,它只会在预定义的特定生命周期节点去查找对应的脚本文件
但可以利用现有钩子来模拟或触发自定义事件,实现“自定义时间”执行操作的效果。这是非常常见的做法
重要提示:.git/目录本身不被版本控制。因此.git/hooks/下的脚本也无法通过Git共享给项目组的其他成员。这是一个本地化的设置。如果需要团队共享钩子,需要额外的步骤

常用Hooks类型

钩子主要分为两大类:客户端钩子(在你的电脑上运行)和服务端钩子(在Git服务器上运行,如GitLab,Gitea,GHE)

客户端钩子(最常见)

  1. pre-commit
  1. prepare-commit-msg
  1. commit-msg
  1. post-commit
  1. pre-push

服务端钩子

  1. pre-receive
  1. update
  1. post-receive

使用Hooks

创建一个钩子:

如何团队共享Git Hooks

如前所述,.git/hooks不纳入版本控制。要让团队所有成员使用相同的钩子,有几种常见方法:

  1. 手动复制:最原始的方法,但非常容易出错且难以维护
  2. 符号链接:将.git/hooks目录链接到项目中的一个受版本控制的目录
  3. 使用第三方工具(推荐) 这些工具可以帮助管理钩子,并确保它们被安装到每个团队成员的本地仓库中
// package.json
{
    "husky": {
        "hooks": {
            "pre-commit": "lint-staged", // 在提交前运行 lint-staged
            "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" // 检查提交信息
        }
    }
}

安装Husky后,它会自动将其脚本安装到你的.git/hooks目录中

Husky运行原理

Husky采用了一种非常巧妙的安装和代理机制。它主要做了两件事

  1. .git/hooks中安装代理脚本
  2. 在项目根目录存储真实的配置
第一步:安装-husky install

当运行npx husky install或通过npm prepare脚本自动安装时,Husky会执行以下操作

  1. .git/hooks中创建文件:Husky会为每一个它支持的Git钩子(如pre-commitcommit-msg,pre-push等)在.git/hooks/目录下创建一个同名的文件
  2. 这些文件时代理脚本:这些文件不是真正的钩子逻辑,而是Husky的统一入口脚本。所有这些都是完全相同的脚本,内容大致如下
#!/bin/sh
# 这是一个Husky创建的代理钩子文件

# 它主要做一件事:去调用Husky的核心程序,并告诉它现在触发的是哪个钩子
husky() {
    # 设置环境变量,告诉husky是哪个钩子被触发了
    export HUSKY_GIT_PARAMS="$*"

    # 运行Husky的核心命令
    npx --no-install husky run "$(besename "$0")"
}

# 运行上面定义的函数
husky "$@"

这个代理脚本的作用是:无论哪个Git钩子被触发,都会把执行权交给husky run命令

第二步:存储配置-在版本控制中

真实的钩子配置并不在.git/hooks里,而是在项目根目录下

  1. Husky的配置目录:Husky默认会在项目根目录创建一个.husky/目录
  2. 存储真实的钩子:在.husky/目录下,可以看到实际执行的脚本文件
your-project/
├── .husky/
│   ├── pre-commit    <-- 真正的pre-commit钩子
│   ├── commit-msg    <-- 真正的commit-msg钩子
│   └── _/           <-- Husky的内部辅助文件
├── .git/
│   └── hooks/
│       ├── pre-commit -> ../../.husky/pre-commit 代理脚本
│       └── ...
├── package.json
└── ...
  1. .husky/pre-commit文件里的内容可能是
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm test # 运行测试
npx lint-staged # 运行lint-staged
第三步:执行流程-钩子被触发时

当在项目中执行git commit

  1. Git发现要执行提交操作,于是查找.git/hooks/pre-commit文件
  2. 找到的时Husky安装的代理脚本,并执行它
  3. 代理脚本运行npx husky run pre-commit命令
  4. husky run命令开始工作
  1. 如果这些命令全部成功(退出码为0),提交继续;如果有任何一个失败,提交中止