Commitlint 与 Husky:现代提交信息校验
本文目录
Commitlint 根据仓库规则检查提交说明,Husky 可以把检查接入本地 Git hook。两者解决的是提交信息一致性和本地反馈速度,不会替代代码评审、测试、CI 或发布治理。本文示例采用当前 Husky v9 目录式 hook;旧版 Husky 的 package.json hooks 与 HUSKY_GIT_PARAMS 不能照搬。
1. Conventional Commits 格式
常见格式为:
type(scope): subject
type描述改动意图,例如feat、fix、docs、refactor、test、build、ci、perf、chore或revert;scope可选,用稳定、简短的模块名说明影响范围;subject用简洁祈使语句说明做了什么,冒号后留一个空格;!和 footer 可表达破坏性变更及 issue 关联,遵循团队 changelog 和发布规则。
例子:feat(reader): remember the last page、fix(auth): clear expired session、docs: explain local setup。这些 type 不是所有团队的强制清单;以仓库实际配置为准,不要因为照抄模板而虚构变更类型。提交说明写“为什么”和用户可见影响,避免无意义的 update、修复问题 或把整段实现塞进标题。
2. 安装与配置
先确认仓库使用的 Node 版本和包管理器,然后在项目根目录添加开发依赖:
npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
不要在已有项目里同时创建多种 lockfile。用团队现有的 npm、pnpm、Yarn 或 Bun 命令等价安装,并提交对应 manifest 与唯一 lockfile。若仓库已有 hooks manager、lint-staged 或 commit-msg 流程,先集成到现有配置,避免多个工具覆盖 core.hooksPath。
在仓库根目录添加 commitlint.config.cjs:
module.exports = {
extends: ['@commitlint/config-conventional'],
};
该配置复用 Conventional Commits 规则。需要自定义 type、scope 或长度时,依据 commitlint 当前规则文档添加明确规则,并给合法/非法消息写自动化测试;不要通过关闭 type-empty、type-enum 等规则让校验名存实亡。提交规则要先和团队达成一致。
3. 添加 Husky commit-msg hook
Husky 官方推荐使用 husky init 初始化。核对它对 package.json 和 .husky/ 的改动,再创建提交信息 hook:
npx husky init
创建 .husky/commit-msg,内容为:
npx --no -- commitlint --edit "$1"
hook 文件名必须是 commit-msg。Git 会把待检查的提交说明文件路径作为第一个参数传入,所以使用 --edit "$1";v9 不再提供 HUSKY_GIT_PARAMS。npx --no 可避免拼错本地依赖时临时下载同名包;CI 依赖安装应按 lockfile 执行。确认脚本在 macOS、Linux 和团队支持的 Windows Git shell 中工作,避免依赖 Bash-only 语法。
Husky 初始化通常会配置 prepare 生命周期来设置 hooks。检查安装和部署流程:若生产构建只安装 dependencies,prepare 可能找不到 devDependency;按 Husky 官方对当前包管理器的说明安全处理,不能盲目加 || true 隐藏其他失败。GUI 使用 Node 版本管理器时,还要确认 hook 环境的 PATH 能找到项目 Node 和本地命令。
4. 不创建提交地验证
先直接调用 Commitlint 检查消息:
printf "%s\n" "feat(reader): remember the last page" | npx --no -- commitlint
printf "%s\n" "bad message" | npx --no -- commitlint
npx --no -- commitlint --from HEAD~1 --to HEAD --verbose
第一条应通过,第二条应因格式不符而失败。第三条用于检查本地提交范围;初始提交、浅克隆或没有 HEAD~1 时需换成实际存在的范围。然后在临时测试仓库验证 hook 的成功与失败路径,不要为了试 hook 在生产分支制造测试提交。
5. CI 才是最终强制边界
本地 hooks 可以被未安装、GUI 环境、HUSKY=0 或 git commit --no-verify 绕过,不能作为唯一合规控制。CI 应对 Pull Request 中的提交范围运行同一版 Commitlint,使用项目 lockfile 安装依赖,并让分支保护要求该检查通过。Fork PR、rebase、merge commit 和 squash merge 会改变提交范围;选择和验证与团队历史策略相匹配的 --from/--to 范围。
6. 故障排查与维护
git config core.hooksPath检查 Git 当前实际使用的 hooks 目录;确认 Husky 安装脚本成功;- 若看到
command not found,先检查 Node/包管理器路径,尤其是 GUI、nvm/fnm/asdf/Volta 等版本管理环境; - 查看 hook 文件名、执行权限和
$1参数引用,确保使用 POSIX shell 可运行的语法; - 确认
commitlint.config.cjs位于配置搜索路径中,并且 CI 和本地加载相同规则; - 不要在脚本里长期设置
HUSKY=0。紧急绕过应有理由、留痕,并由 CI 重新执行检查。
从旧 Husky 配置迁移
旧项目可能在 package.json 中使用 husky.hooks、commitlint -E HUSKY_GIT_PARAMS 或 .huskyrc。迁移时先记录现有 hook 列表和 core.hooksPath,逐个转成 .husky/<hook-name> 文件,再在干净克隆、安装依赖和 GUI 环境中测试。避免新旧两套配置同时运行或覆盖团队已有 hooks。
官方参考:Commitlint 本地设置、Commitlint 配置与规则、Husky 快速开始、Husky 迁移 v4、Husky 故障排查。
Live Notes
留言提交后会先进入审核,审核通过后对其他读者公开。