今天合代码准备发布新版本,点开 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 钩子拦截脚本:
# 激活 huskynpm 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 在提交前硬性拦截?