Git提交信息乱七八糟?这篇帮你规范化
从「凭心情写」到团队统一格式,聊聊真实落地方案
不知道你们团队有没有这种场景:打开 Git 历史,看到的是一堆「update」「fix bug」「修改」「666」——好不容易写的代码,提交记录却像朋友圈文案一样随意。等你想找某个功能什么时候加的、为什么改了,对不起,大海捞针。
或者另一种:review 代码的时候,提交信息写的是「优化」,结果这个提交干了两百件事——加功能、改样式、修 bug、删文件全塞一块,reviewer 看了想打人。这种提交历史对于团队协作来说,几乎等于没有历史。
本文聊聊怎么用 Conventional Commits(约定式提交)配合 husky + lint-staged + commitlint 这套工具链,真正让团队提交信息统一、可维护、自动生成 CHANGELOG。实操向,不废话。
一、痛点场景——你中了几条?
想找「登录模块是什么时候加的?」——只能靠猜,翻到吐血。
产品问「这次更新了哪些功能?」你埋头在几百条提交里挑,眼睛都快瞎了。
有人写中文,有人写英文,有人用 feat:有人用 feature:,还有人在里面写小作文。
提交代码 push 上去,CI 报红,原来是 commit message 格式被 lint 拦了——这时你已经在 PR 里躺好了。
这些问题,约定式提交 + 自动化工具可以一套带走。
二、Conventional Commits:约定式提交是什么?
Conventional Commits 是一套社区约定的提交信息规范,核心思路很简单:用固定格式描述每次提交,让历史可读、可解析、可自动化。
2.1 格式长这样
- type(必需):提交类型,英文小写
- scope(可选):影响范围,用括号包裹——比如 feat(auth):、fix(payment):
- description(必需):简短描述,一句话说明这次干了什么,用中文或英文都行,团队统一即可
- body(可选):详细说明,换行写
- footer(可选):用于写关联的 issue、breakding change 等
2.2 常用 type 清单
2.3 正面 vs 反面对比
| ❌ 别这样写 | ✅ 规范写法 |
|---|---|
| update | feat(user): 添加第三方登录功能 |
| fix bug | fix(order): 修复结算页金额显示错误 |
| 改了点东西 | refactor(payment): 重构支付回调逻辑 |
| 1 | docs: 更新 README 安装说明 |
| Merge branch 'xxx' | (merge 提交例外,不需要改) |
2.4 带 body 和 footer 的完整示例
这就是一份标准的好提交。reviewer 一眼就知道这次干了什么、有没有破坏性变更、关联了哪个 issue。
三、工具配置:husky + lint-staged + commitlint
规范定好了,得有人执行才行。总不能靠人工 code review 来纠正提交格式——太慢了,而且人总有疏忽。
3.1 husky——Git 钩子自动化
husky 的作用是让你在 Git 操作时自动触发脚本。比如你 git commit 的时候,自动跑一个脚本来检查提交信息格式。
安装(以 npm 为例):
这会在你项目里创建一个 .husky/ 目录,里面放各种 Git hook 脚本。初始化后会生成一个 .husky/pre-commit 文件,每次 git commit 之前会自动执行这个脚本。
3.2 lint-staged——只检查暂存区的文件
lint-staged 的作用很明确:只检查被 staged(暂存区)的文件),而不是整个项目。这很重要——你的修改文件可能是半成品,不在暂存区的根本不该被检查。
在 package.json 里加配置:
这样每次 commit,lint-staged 会自动用对应的 linter 检查暂存区文件,不影响你正在写的其他文件。
3.3 commitlint——检查提交信息格式
commitlint 是核心:它读取你写的 commit message,按规则校验,不合格就直接拒绝 commit。配合 husky 的 pre-commit 钩子,你 push 之前就能发现问题。
创建配置文件 commitlint.config.js(或 .js / .ts / .yaml 都可以):
用 YAML 格式的等效配置:
然后把 commitlint 加入 husky pre-commit 钩子:
这行命令会在 .husky/commit-msg 文件里写入:每次 commit 时,用 commitlint 校验提交信息,不合格就拒绝 commit。
3.4 完整 pre-commit 钩子内容
最终你的 .husky/pre-commit 大概长这样:
.husky/commit-msg 长这样:
配置完成后,体验是这样的:
git commit -m "feat: 新增用户注册功能" → 成功提交❌
git commit -m "update" → 被 commitlint 拦截,提示格式错误,拒绝提交
四、自动生成 CHANGELOG
这是规范提交的最大福利之一。提交格式统一了,CHANGELOG 就能自动生成。
4.1 standard-version / release-please
standard-version(npm 包)根据提交类型自动决定版本号并生成 CHANGELOG:
运行:
它会:
- 读取所有 Conventional Commits
- 根据
feat:→ 升级 minor 版本,fix:→ 升级 patch 版本 - 自动生成/更新
CHANGELOG.md - 生成一个 git tag
生成的 CHANGELOG 大概长这样:
4.2 conventional-changelog-cli
如果你想更灵活一点,用 conventional-changelog-cli:
加上 -r 1(release count = 1)表示只输出上一个 tag 以来的变更,适合在发版时执行。
五、常见错误和避坑
❌ 错误 1:type 用了大写
git commit -m "FEAT: 新增登录功能" — ❌ 大写会被 commitlint 拒绝git commit -m "feat: 新增登录功能" — ✅ 必须全小写
❌ 错误 2:description 为空或写太模糊
git commit -m "feat: update" — ❌ update 是啥?git commit -m "feat(user): add login with phone verification" — ✅ 说清楚做了什么
❌ 错误 3:description 以句号结尾
git commit -m "feat: 新增用户注册功能." — ❌ 不要句号结尾git commit -m "feat: 新增用户注册功能" — ✅ 简洁直接
❌ 错误 4:一个提交干了 N 件事
git commit -m "fix: 修 bug + 加功能 + 改样式" — ❌ 一个提交只做一件事分成三个 commit:
fix: ...、feat: ...、style: ... — ✅ 每件事独立可追溯
❌ 错误 5:忘了安装 husky hook
换机器后记得重新跑 npx husky install,否则本地 hook 不生效,CI 上才被拦就很尴尬了。建议在 package.json 的 postinstall 里加上:
❌ 错误 6:Merge commit 不走 commitlint
Merge commit(合并分支时产生的提交)格式是 Merge branch 'xxx',不符合规范,会被拦。通常在 commitlint.config.js 里跳过这类:
❌ 错误 7:commit message 标题超长
六、给团队的一点建议
规范落地最重要的一点不是工具,是共识。工具只是辅助,团队成员真正理解「为什么要这样写」才能长期坚持。
几个实操建议:
- 新成员 onboarding:把提交规范写进 README 或 CONTRIBUTING.md,第一天就让新人知道该怎么写
- CI 也要装 commitlint:本地可能被绕过,CI 一定要有,防止漏网之鱼
- 从小团队开始:不要一开始就搞一堆规则,先从 feat/fix/docs/chore 四个 type 开始,够了再加
- 别过度工程化:有些团队配了一堆工具,最后大家都在想办法绕过它。够用就行
- 善用 AI:写提交信息不知道用哪个 type?让 AI 帮你判断,然后你审核——比硬背快多了
规范的价值在于长期维护。一份好的提交历史,在半年后做技术回顾、追查 bug、准备发版说明的时候,价值就体现出来了。
常见问题
A: 这类工具一般有明确的输入框和输出框,按提示输入内容,点击对应按钮即可得到结果。建议先用简单示例测试功能是否正常,再处理实际数据。
A: 根据具体工具类型决定。格式转换工具适合处理第三方数据,编码工具适合加密传输,压缩工具适合文件上传前处理。多积累工具使用经验,遇到问题时能快速判断用哪个工具解决。
A: 不同工具有不同侧重,重点是理解原理。可以同时安装多个类似工具,实际使用中对比效果,选择最顺手的一个。随着使用经验增加,你也能判断工具的好坏。