今天合代码准备发布新版本,点开 Git 提交历史,血压瞬间拉满。一排排提交记录里写着“fix”、“update”、“测试一下”、“111”甚至干脆就是“debug”。这些毫无信息量的 Commit Message 让人根本看不出这次发版到底修了什么 Bug,上了什么功能。
一旦项目规模变大,不规范的 Git 提交记录会让追溯历史问题变得极其痛苦。如果每次发布 CHANGELOG 还要靠人工去翻 PR 一个个肉眼整理,这纯粹是在浪费生命。
规范化提交记录的最佳时机是在本地 commit 时直接拦截。为了解决这个问题,我们团队在前端和 Node 后端项目中,引入了 husky 和 commitlint 构建的 Git Hook 约束体系。
以下是完整的工具链集成配置与初始化步骤,直接拷过去就能在你的项目里跑起来:
第一步,在项目根目录下安装依赖:
npm install --save-dev @commitlint/config-conventional @commitlint/cli husky lint-staged
第二步,在根目录下编写 commitlint.config.js 规则文件:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// 强制 scope 必须小写
'scope-case': [2, 'always', 'lower-case'],
// 强制 subject 不能为空
'subject-empty': [2, 'never'],
// 限制首字母不能大写
'subject-full-stop': [2, 'never', '.'],
// 限制 header 的总长度不超过 72 个字符
'header-max-length': [2, 'always', 72],
// 约束 type 的取值范围,必须是以下约定类型之一
'type-enum': [
2,
'always',
[
'build', // 构建系统、依赖变更(例如 glup, webpack, npm 等)
'chore', // 构建过程或辅助工具的变动(不影响源码及测试)
'ci', // CI 配置文件及脚本的变更
'docs', // 文档修改(Markdown 等)
'feat', // 新功能(feature)
'fix', // 修补 Bug
'perf', // 性能优化
'refactor', // 代码重构(不包括 Bug 修复或功能新增)
'revert', // 回滚到历史 Commit
'style', // 代码格式变更(不影响代码逻辑的空格、分号等格式)
'test' // 增加测试或修改已有测试
]
]
}
};
第三步,在项目的 package.json 中配置 husky 自动初始化以及 lint-staged 钩子:
{
"name": "homework-money-printer",
"version": "1.0.0",
"scripts": {
"prepare": "husky install"
},
"lint-staged": {
"src/**/*.{js,ts,tsx}": [
"eslint --fix",
"prettier --write"
]
}
}
第四步,在本地执行以下命令激活 Git Hooks,并添加 commit-msg 钩子拦截脚本:
# 激活 husky
npm run prepare
# 添加 commit-msg 校验钩子
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
# 添加 pre-commit 代码质量与格式化校验钩子
npx husky add .husky/pre-commit 'npx lint-staged'
这套管线配置搞定后,开发者再想像以前那样随手写一句 git commit -m "update" 就会直接报错拒绝提交。团队成员必须规规矩矩地按照 feat(auth): add google oauth login 或 fix(api): solve db memory leak 的标准格式来提交代码。
虽然前期在推行时大家觉得有些被规则绑架,心智负担有点高,但两周下来,项目的 Git 树清晰得像教科书一样,用语义化发布工具也可以一键生成漂亮又规范的 Release Changelog。
你们团队在落地 Conventional Commits 时有没有遇到开发同学的强烈吐槽?大家一般是用交互式的 commitizen 来引导编写,还是跟我们一样采用强硬的 commitlint 在提交前硬性拦截?