基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

什么是 Git Hooks(钩子)?

知识点图片

Git Hooks(Git 钩子) 是 Git 版本控制系统中的一个非常强大且实用的功能。

简单来说:Git Hooks 就是一些自定义的脚本,它们会在 Git 执行特定操作(如提交 commit、推送 push、合并 merge 等)之前或之后自动运行。

你可以把它想象成 Git 里的“触发器”或“拦截器”。通过编写这些脚本,你可以自动化你的开发工作流、强制执行代码规范,或者防止将错误的代码推送到远程仓库。


1. Git Hooks 存在哪里?

在每一个 Git 仓库中,Hooks 都存放在隐藏目录 .git/hooks/ 下。

如果你打开一个新初始化的 Git 仓库的 .git/hooks/ 文件夹,你会看到很多以 .sample 结尾的文件(例如 pre-commit.sample)。这些是 Git 官方提供的示例脚本。如果你想启用某个特定的钩子,只需要把文件名后面的 .sample 后缀删掉,并赋予该文件可执行权限即可。

注意: Hooks 脚本可以用任何你机器上能运行的脚本语言编写,最常见的是 Shell 脚本(Bash),但你也可以用 Python、Ruby、Node.js 甚至 Perl 来写。


2. Git Hooks 的分类

Git Hooks 主要分为两类:客户端钩子(Client-Side)服务端钩子(Server-Side)

A. 客户端钩子(在开发者的本地电脑上运行)

这些钩子由本地的 Git 操作触发,最常用于提交(Commit)工作流:

  • pre-commit(最常用) 在输入提交信息(commit message)之前运行。它经常被用来检查代码格式(Linting)、运行单元测试、或者检查是否包含了忘记删除的调试代码(如 console.log)以及敏感信息(密码、密钥)。如果脚本以非零状态(exit 1)退出,Git 就会中止这次提交。
  • prepare-commit-msg:在 Git 生成默认提交信息之后、启动编辑器让用户修改之前运行。常用于自动在 commit message 中插入当前的 Jira 任务号或分支名。
  • commit-msg:在开发者编写完提交信息后运行。常用于验证提交信息的格式是否符合团队规范(例如强制使用 feat: xxxfix: xxx 的格式)。
  • post-commit:在整个提交过程完成后运行。通常用于通知(例如发邮件或给 Slack 发消息),不能用来中止提交。
  • pre-push:在执行 git push 命令时、数据推送到远程仓库之前运行。常用于在推送到服务器前运行更耗时的完整测试套件,以节省 CI(持续集成)服务器的资源。

B. 服务端钩子(在远程服务器上运行,如 GitLab, GitHub Enterprise 等)

这些钩子用于强制执行服务器端的策略,它们在接收到别人 push 的代码时触发:

  • pre-receive:在服务器接收到推送的数据时,更新引用之前运行。可以用来拒绝那些不符合规范的代码推送(例如禁止强制推送 push -f,或者必须所有的 commit 都包含指定的 ticket 编号)。
  • post-receive:在代码被成功推送到服务器后运行。常用于触发 CI/CD 流水线(如 Jenkins)、更新线上服务器的代码(自动化部署)或发送邮件通知。

3. Git Hooks 的实际应用场景

  • 代码质量控制:在 pre-commit 阶段运行 ESLint (JS/TS)、Flake8 (Python) 或 Checkstyle (Java),如果代码不规范,直接拒绝提交。
  • 代码格式化:在提交前自动运行 Prettier 或 Black 来格式化代码,确保所有人提交的代码风格一致。
  • 防止敏感信息泄露:使用工具(如 Talisman 或 git-secrets)在 pre-commit 中扫描代码,防止误提交 AWS 密钥或数据库密码。
  • 规范 Commit 记录:在 commit-msg 阶段使用 commitlint,确保提交信息符合 Semantic Versioning(语义化版本)规范。

4. 如何编写一个简单的 Git Hook?

假设我们要写一个 pre-commit 钩子,阻止提交包含 "TODO" 字样的代码:

  1. 进入 .git/hooks/ 目录。
  2. 创建或修改文件名为 pre-commit(没有后缀)。
  3. 写入以下 Shell 代码:
bash
#!/bin/bash

# 检查即将提交的代码中是否包含 "TODO"
if git diff --cached | grep -q "TODO"; then
    echo "❌ 错误:你的代码中包含未完成的 'TODO',请修改后再提交!"
    exit 1 # 退出码非 0,中止提交
fi

echo "✅ 检查通过,允许提交!"
exit 0 # 退出码为 0,允许提交
  1. 给文件赋予执行权限:chmod +x .git/hooks/pre-commit
  2. 现在,如果你尝试提交包含 "TODO" 的代码,Git 就会报错并停止提交。

5. 如何跳过 Git Hooks?

有时候你可能处于紧急情况,或者确认代码没问题但不符合规范,想要强行提交。你可以使用 --no-verify(或简写 -n)参数来跳过客户端钩子:

bash
git commit -m "紧急修复" --no-verify
# 或者
git push origin main --no-verify

(注意:服务端钩子无法通过本地命令跳过,除非你有服务器的管理员权限。)


6. 现代开发中的 Git Hooks 工具

痛点: .git/hooks/ 目录不会被 Git 纳入版本控制。也就是说,你在本地写好的完美 Hook 脚本,你的同事是拿不到的,除非你让他们手动复制一遍。

解决方案: 为了让整个团队共享 Hooks 配置,现在主流的做法是使用第三方自动化工具

  • Husky (前端/Node.js 生态中最流行):可以通过 package.json 配置,并在 npm install 时自动安装和绑定 Hooks。
  • pre-commit (Python 生态及通用型项目常用):使用 .pre-commit-config.yaml 配置文件,可以非常方便地引入社区写好的各种验证脚本。
  • Lefthook:一个用 Go 编写的、速度极快的并行 Git Hooks 管理工具。

总结

Git Hooks 就是 Git 生命周期的拦截器脚本。利用它,团队可以将“靠自觉”的代码规范变成“强制性”的流程,从而大大提高代码质量和开发效率。

00:00
00:00