如何用 AI 自动生成规范的 Git 提交信息:从暂存区 diff 到 Conventional Commit
在团队协作中,Git 提交信息往往是一个容易被忽略、但会持续影响维护效率的细节。
很多人都遇到过类似情况:代码改完了,准备提交时却在 git commit -m 后面犹豫很久;有时写成"修改代码",有时写成"update",过一段时间再看提交记录,几乎无法判断当时改了什么。
Conventional Commits 解决了格式统一的问题,但没有解决"如何准确总结这次变更"。这篇文章记录一下我做 zhcommit 时采用的一套实现思路:读取 Git 暂存区 diff,交给 OpenAI 兼容接口分析,再经过本地清洗和确认后完成提交。
为什么读取暂存区,而不是整个工作区
工具的输入应该和最终提交内容一致。因此,核心命令使用的是:
bash
git diff --cached --no-ext-diff
这样有两个好处:
- 未执行
git add的本地修改不会被误分析; - AI 生成的描述天然对应当前准备提交的内容。
生成过程中还会再次读取暂存区。如果期间暂存区发生变化,工具会停止提交并提示重新运行。这一步看起来有些保守,但比提交一条和代码不匹配的信息更安全。
让模型只负责"理解",不要直接信任输出
AI 返回的内容不能直接传给 git commit。我把流程分成三层:
text
diff
↓
模型生成
↓
本地清洗和校验
↓
用户确认
↓
git commit
项目限定提交类型为:
text
feat fix docs style refactor perf test build ci chore revert
同时对主题行、正文要点数量和长度进行限制。如果模型输出 Markdown 代码围栏、解释过程或非标准类型,会在本地做有限修正;如果无法识别出合法提交信息,则要求重新生成,而不是冒险提交。
根据变更规模决定提交信息详略
小改动和大改动适合不同的提交信息:
| 变更规模 | 输出 |
|---|---|
| 不超过 2 个文件且不超过 30 行 | 一行主题 |
| 超过任一阈值 | 主题加 3~6 条要点 |
规模由 git diff --cached --numstat 统计,而不是让模型自行判断。这样同一项目的行为更稳定,也更容易测试。
例如小改动可以是:
text
fix: 修复配置文件读取异常
较大的改动则可能是:
text
refactor: 重构配置加载与提交生成流程
- 保留用户已有的接口和模型配置
- 增加配置内容的格式校验
- 在提交前重新确认暂存区未发生变化
大型 diff 不能简单地一次发送
当变更很大时,把完整 diff 放进一次请求并不可靠。zhcommit 会优先按照文件、diff hunk 和换行边界拆分,单个片段过长时才使用字符切分。
处理流程大致是:
text
大型 diff
↓
拆成多个片段
↓
最多 3 路并发总结
↓
必要时分组压缩摘要
↓
最终生成提交信息
每个批次的结果会按照原始顺序汇总,而不是按照请求返回顺序汇总。某一批出现不可恢复错误时,还会取消同一轮中尚未完成的请求,减少不必要的网络和 Token 消耗。
为什么还要保留人工确认
自动生成不等于自动执行。默认流程会把结果打印出来,让用户选择:
- 回车或
Y:使用当前信息提交; r:重新生成;n:取消提交。
在 CI 或明确接受自动提交的场景,才使用:
bash
zhcommit --yes
使用方式
安装后先把代码加入暂存区:
bash
npm install -g zhcommit
git add src/
zhcommit
首次运行会配置 OpenAI 兼容接口地址、API Key 和模型。配置文件保存在用户主目录,例如 Windows 下是:
text
C:\Users\<用户名>\zhcommit.json
查看帮助:
bash
zhcommit --help
zhcommit config --help
总结
AI 在 Git 提交场景中的价值,不是替开发者决定提交内容,而是减少重复性的文字总结工作。真正影响可靠性的,往往是外围设计:输入范围是否明确、输出是否校验、大 diff 是否拆分、提交前是否再次检查,以及是否保留人工确认。
如果你的团队已经在使用 Conventional Commits,但经常因为提交信息质量不稳定而困扰,可以把"生成"和"校验"拆开设计,再根据项目实际情况决定是否引入类似工具。