Featured image of post 用于自动化的 Git Hooks:超越代码质量Featured image of post 用于自动化的 Git Hooks:超越代码质量

用于自动化的 Git Hooks:超越代码质量

探索用于自动化的 Git 挂钩,涵盖预提交、预推送、提交消息挂钩、husky、lint-staged、自定义脚本、共享挂钩和 CI 等效项。

介绍

Git 挂钩是在 Git 生命周期中的特定点自动运行的可执行脚本。虽然许多开发人员仅将它们与代码格式化和 linting 联系起来,但它们的潜力远远超出了工作流程自动化、项目管理和团队协作。本文探讨了如何利用 Git hook 来实现全面的自动化策略。

了解 Git Hook

Git 挂钩驻留在每个存储库的 .git/hooks/ 目录中。它们是用任何语言(bash、Python、Node.js 或 Ruby)编写的标准可执行脚本。挂钩分为两类:在开发人员计算机上运行的客户端挂钩(预提交、预推送、提交消息)和在远程存储库上执行的服务器端挂钩(预接收、更新、后接收)。

钩子生命周期按时间顺序跟随 Git 操作。在提交期间,挂钩按以下顺序执行:pre-commitcommit-msgpost-commit。对于推送,顺序为 pre-push(客户端)→ pre-receiveupdatepost-receive(服务器)。

与 Husky 设置 Hook

通过将脚本放置在 .git/hooks/ 中来手动管理挂钩对于团队来说是不切实际的,因为 Git 不跟踪该目录。 Husky 通过允许在存储库中配置挂钩并在团队中共享来解决这个问题。

Husky v9+ 的安装非常简单:

npx husky init

这将创建一个 .husky/ 目录,其中挂钩脚本是纯文本文件:

# .husky/pre-commit
npx lint-staged

对于 CI 环境,可以通过设置 HUSKY=0 来跳过钩子:

HUSKY=0 git push

集成 lint-staged

Lint-staged 仅在暂存文件上运行 linter,从而保持快速的预提交检查:

{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{css,scss}": ["stylelint --fix", "prettier --write"]
  }
}

预提交挂钩:第一道防线

预提交挂钩在每次提交之前执行,非常适合快速、本地化检查。

检查类型工具目的
绒毛ESLint、stylelint执行代码风格标准
格式化更漂亮,dprint一致地自动格式化代码
类型检查打字稿 --noEmit及早发现类型错误
秘密侦查Secretlint,松露Hog防止凭证泄露
文件验证自定义脚本阻止大文件或 TODO 提交

全面的预提交配置:

# .husky/pre-commit
npx lint-staged
npx tsc --noEmit
npx secretlint "**/*"

性能至关重要 - 预提交挂钩应在五秒内完成,以避免中断开发流程。


预推挂钩:CI 安全网

预推送挂钩在代码到达远程存储库之前运行,这使得它们非常适合长时间运行的验证:

# .husky/pre-push
npm test
npm run build
npm audit

分支命名验证确保整个团队的一致性:

#!/bin/sh
branch=$(git rev-parse --abbrev-ref HEAD)
if ! echo "$branch" | grep -qE '^(feature|bugfix|hotfix)/[A-Z]+-[0-9]+-'; then
  echo "Error: Branch name must match feature/ABC-123-description"
  exit 1
fi

使用 commitlint 进行提交消息挂钩

强制执行传统的提交消息可确保一致的、可解析的历史记录。将 commitlint 与 Husky 一起使用:

# .husky/commit-msg
npx --no -- commitlint --edit $1

commitlint.config.js 中配置 commitlint:

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'subject-max-length': [2, 'always', 50],
    'body-max-line-length': [2, 'always', 72],
  },
};

有效的提交消息遵循 <type>(<scope>): <description> 格式:

feat(auth): implement OAuth 2.0 refresh token rotation
fix(api): handle null pointer in user deserialization
docs(readme): update installation instructions

提交后和合并后挂钩

合并后挂钩对于依赖管理特别有用。当锁定文件更改时自动安装更新的依赖项:

# .husky/post-merge
changed=$(git diff HEAD~1 --name-only)
if echo "$changed" | grep -q "pnpm-lock.yaml"; then
  pnpm install
fi

CI 等效策略

最稳健的模式可确保钩子和 CI 运行相同的检查。提取两个环境调用的共享脚本:

#!/bin/sh
# scripts/validate.sh - called by both hooks and CI
npm run lint
npm run typecheck
npm test

本地挂钩应尽可能发出警告或自动修复,而 CI 则严格执行。这创建了一个安全网:开发人员在推送之前发现问题,而 CI 捕获任何漏掉的东西。


结论

Git hooks 是一个强大的自动化层,其功能远远超出了代码格式化的范围。将 Husky 与 lint-staged 结合起来为大多数项目提供了推荐的基线。预推送钩子在代码到达 CI 之前添加了一个安全网,并且 commitlint 确保了干净、可解析的提交历史记录。最终目标是提供无缝的开发人员体验,其中自动化处理重复检查,使团队能够专注于逻辑和设计。