git 提交信息需规范:首行50字内祈使句描述改动,空行后说明原因及php版本影响,正确使用feat/fix/chore/refactor/docs等前缀,关联issue,避免amend破坏bisect,通过钩子校验格式。

提交信息不写清楚,git log 就等于翻天书
PHP 项目里,git commit 的信息不是凑数的。别人(包括三个月后的你自己)靠它快速判断一次变更是否影响路由、是否动了数据库迁移、有没有修复某个 DateTimeZone 解析异常。空泛写“fix bug”或“update files”,等于把线索掐断在源头。
实操建议:
- 首行控制在 50 字以内,用祈使句开头:比如
fix: handle null timezone in DateTimeFactory,而不是Fixed a bug with timezone - 空一行后写正文,说明「改了什么」和「为什么这么改」,尤其涉及 PHP 版本兼容性时要提:比如 “PHP 8.1+ 要求
DateTimeZone::__construct()第二个参数不能为null,此处兜底为'UTC'” - 如果这次提交关联 issue,结尾加
Resolves #123或Refs #456,GitHub/GitLab 会自动联动
PHP 项目常用前缀别乱套,chore 和 refactor 区别很大
前缀不是装饰,它直接决定 CI 流程是否触发版本号变更、是否生成 CHANGELOG。PHP 生态里尤其要注意:feat 和 fix 会影响 composer update 行为(比如某些工具按 commit 前缀判断是否需重跑测试)。
常见错误现象:
立即学习“PHP免费学习笔记(深入)”;
- 把修改
phpstan.neon配置写成feat: add phpstan rules—— 实际应为chore: adjust phpstan level to php 8.2,因为没改变运行时行为 - 重构一个
UserService类的依赖注入方式,但没改接口或外部调用逻辑,写成fix就会误导别人以为修了缺陷 -
docs只用于 README、PHPDoc 注释等纯文档;给src/下函数补类型提示属于refactor(影响静态分析),不是docs
涉及 PHP 版本升级的提交,必须标出具体影响范围
PHP 从 7.4 升到 8.0/8.1/8.2 不是平滑过渡。git blame 找到某行代码时,如果提交信息没写清 “drop support for PHP 7.4 array syntax in ConfigLoader”,你就得手动查 composer.json 的 platform.php 设置、看 php -l 报错位置、再比对 changelog——三倍时间成本。
实操建议:
- 批量替换
??为??=或改用match表达式时,提交信息里明确写出最小支持版本:feat: use match expression (PHP 8.0+) in RouteResolver - 删除
create_function()调用,不能只写 “remove deprecated function”,要写refactor: replace create_function with anonymous function (PHP 7.2+) - 如果提交同时包含语法升级和逻辑调整,拆成两个 commit:一个只做语法适配(
chore),一个做功能改动(feat或fix),否则 review 时容易漏掉语义变更
git commit --amend 不是后悔药,PHP 项目里慎用
PHP 项目常有 CI 检查提交信息格式(比如用 commitlint 验证前缀),但有人习惯先 git commit -m "wip",再 --amend 改信息。问题在于:如果已 git push,强制推送会破坏他人本地分支的 git bisect 能力——而 PHP 的“某次更新后 symfony/console 命令报 TypeError”类问题,正依赖 bisect 快速定位。
更稳妥的做法:
- 用
git commit --no-edit先提交,再通过git rebase -i HEAD~2合并/编辑最近几次提交信息(适合还没 push 的场景) - 如果已 push 且多人协作,宁愿多一个
chore: correct previous commit message提交,也别强制覆盖历史 - 把提交信息规范写进
.husky/pre-commit钩子,用commit-msg钩子校验格式,比事后 amend 更省事
真正难的不是写对格式,是每次敲 git commit 时,想清楚这行代码在 PHP 8.3 的 #[\Override] 语义下是否还成立、会不会让下游包的 phpstan 分析失败——这些细节,全靠提交信息锚定上下文。











