人人都会AI编程

20.2 Husky + lint-staged + commitlint:提交前校验与提交规范

更新时间:2026-07-10

在团队协作中,代码质量和提交信息的规范性直接影响项目的可维护性和历史追溯能力。通过自动化工具,可以在 Git 提交(commit)之前强制执行代码检查和提交信息格式校验,避免不符合规范的代码进入仓库。这一节介绍三个核心工具的搭配使用:

  • Husky:管理 Git hooks(钩子),在特定 Git 操作发生时自动执行脚本。
  • lint-staged:只对暂存区(staged)的文件运行检查,速度快且精准。
  • commitlint:校验 commit message 是否符合约定格式(如 Conventional Commits 规范)。

为什么需要这套工具链

在代码评审和持续集成之前,将基础的质量关卡前置到开发者本地的提交动作中,可以:

  • 防止存在语法错误或格式问题的代码被推送到远程。
  • 统一 commit message 风格,方便生成 CHANGELOG 和版本号。
  • 避免浪费 CI 资源去跑已经可以在本地快速修复的问题。
  • 减少代码评审中的规范性讨论,让评审聚焦在逻辑和设计上。

安装与配置 Husky

Husky 是 Git hooks 的现代管理工具,推荐使用 v9 及以上版本(原生 ESM 支持)。

1. 安装 Husky:

npm install --save-dev husky

2. 初始化 Husky(在项目根目录执行):

npx husky init

这一步会在项目根目录创建 .husky/ 文件夹,并在 package.json 中添加 prepare 脚本,确保每次 npm install 后 hooks 自动安装。

生成的 .husky/pre-commit 文件已经包含一个基本示例:

npm test

你可以将其替换为 lint-staged 的调用。

安装与配置 lint-staged

lint-staged 可以让你定义针对不同文件扩展名的检查命令,并且只作用于 Git 暂存区的文件。

1. 安装:

npm install --save-dev lint-staged

2. 在 package.json 中添加配置:

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

上述配置表示:对暂存的 JS/TS 文件先运行 ESLint 自动修复,再运行 Prettier 格式化;对 CSS 文件先用 stylelint 修复再用 Prettier;对 JSON 和 Markdown 文件仅格式化。

3. 将 lint-staged 挂载到 pre-commit hook:

修改 .husky/pre-commit 文件,内容为:

npx lint-staged

现在每次 git commit 时,Husky 会触发 pre-commit 钩子,执行 lint-staged,只检查并修复暂存区文件。如果任何命令失败(例如 ESLint 发现无法自动修复的错误),提交会被阻止,你可以在本地修复后再次提交。

安装与配置 commitlint

commitlint 检查 commit message 是否符合预设的规范,最常用的是 Conventional Commits 格式。

1. 安装 commitlint 和规范配置:

npm install --save-dev @commitlint/cli @commitlint/config-conventional

2. 创建配置文件 commitlint.config.js(或 .commitlintrc.js):

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    // 可以自定义规则,这里使用默认约定
  }
};

Conventional Commits 格式为:

type(scope?): subject

[optional body]

[optional footer]

例如:

  • feat: 添加用户登录功能
  • fix: 修复列表翻页后数据未重置的问题
  • docs: 更新 README 中的安装步骤
  • chore: 升级依赖版本

3. 挂载 commitlint 到 commit-msg hook:

创建 Husky 的 commit-msg hook,在 .husky/commit-msg 文件中写入:

npx --no -- commitlint --edit $1

也可以使用 Husky 命令添加:

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

这条命令会在每次提交时读取 .git/COMMIT_EDITMSG 临时文件,检查 commit message 是否符合规范,不符合则拒绝提交。

实际工作流演示

假设你修改了一个 TypeScript 文件并准备提交:

  1. 使用 git add 将文件加入暂存区。
  2. 执行 git commit -m "fix: 修复按钮点击无响应的问题"
  3. Husky 触发 pre-commit 钩子:
  • lint-staged 查找暂存区的 TS 文件。
  • 运行 ESLint 修复并检查,如果通过,继续运行 Prettier 格式化。
  • 如果一切通过,进入下一步。
  1. Husky 触发 commit-msg 钩子:
  • commitlint 解析 fix: 修复按钮点击无响应的问题,符合规范,提交成功。
  1. 提交完成。

如果 commit message 写成 修复了一个bug,commitlint 会报错:

✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

并给出修正提示,提交会被阻止,直到信息格式正确。

常见问题与调整

Q:ESLint 修复后文件已变更,但提交没有包含这些变更怎么办?

lint-staged 默认会在修复后自动重新 git add 被修改的文件。如果由于某些原因没有自动添加,可以在 lint-staged 配置中显式设置:

"lint-staged": {
  "*.js": ["eslint --fix", "prettier --write", "git add"]
}

但 lint-staged v10+ 已不再需要手动 git add,默认行为就是如此。

Q:如何跳过钩子检查?

可以使用 Git 的 --no-verify 参数临时跳过所有钩子(不推荐经常使用):

git commit --no-verify -m "临时提交"

Q:团队中有多人开发,如何保证每个人安装依赖后自动启用 Husky?

package.json 中的 prepare 脚本会在 npm install 时自动执行 husky,无需额外操作。确保该脚本存在:

"scripts": {
  "prepare": "husky"
}

集成到 CI 环境

尽管本地钩子已经能拦截大部分问题,但仍建议在 CI(持续集成)环境中再次运行相同的检查,作为双重保障。例如,在 GitHub Actions 中:

- name: Commitlint
  run: npx commitlint --from=HEAD~1 --to=HEAD

这样可以避免某个开发者绕过本地钩子直接推送不符合规范的提交。

小结

Husky + lint-staged + commitlint 的组合是前端工程化的标准实践之一。它通过 Git 钩子将代码质量和提交规范校验自动化、本地化,在问题进入仓库之前就将其拦截,显著提升团队协作效率和代码库的健康度。配置过程简单,一旦设置完毕,几乎可以“忘记它们的存在”,直到某次不合规操作被友好地提示。