git commit 规范

1. 为什么需要 Commit 规范?

在深入格式之前,先理解“为什么”能让你坚持遵守:

  • 代码审查 (Review) 更高效:清晰的标题能让 Reviewer 快速判断修改的范围和性质。
  • 自动化生成 Changelog:规范的格式可以直接脚本提取生成发布日志。
  • 版本回溯与定位 (Bisect):当出现 Bug 需要回滚时,规范的提交记录能帮你快速定位是哪个 featfix 引入的问题。
  • 语义化版本控制:提交类型(如 fix vs feat)直接对应版本号的 Patch 或 Minor 更新。

2. 标准格式结构

一个标准的 Commit Message 包含三个部分:HeaderBodyFooter

<Type>(<Scope>): <Subject>
// 空一行
<Body>
// 空一行
<Footer>

第一部分:Header (必填)

这是最关键的一行,必须简洁明了(建议不超过 50 或 72 个字符)。

  • Type (类型):用于说明 commit 的类别。常见的类型有:
    • feat:新功能 (Feature) -> 对应语义化版本的 MINOR
    • fix:修补 Bug -> 对应语义化版本的 PATCH
    • docs:仅文档更改 (Documentation)。
    • style:不影响代码含义的更改 (空格、格式化、缺少分号等)。
    • refactor:重构代码 (既不是新增功能,也不是修改 Bug)。
    • perf:优化性能的更改。
    • test:增加测试或更新现有测试。
    • chore:构建过程或辅助工具的变动 (如文档生成、依赖升级),不影响源码。
    • ci:CI 配置文件或脚本的修改 (如 GitHub Actions, Travis)。
    • revert:回滚之前的提交。
  • Scope (范围):(可选) 用于说明 commit 影响的范围。
    • 例如:feat(user-auth): add login logic,括号里的 user-auth 就是 scope,指明了修改的是用户认证模块。
  • Subject (简述):commit 的简短描述。
    • 使用祈使句(如 “change” 而不是 “changed” 或 “changes”)。
    • 不要以句号结尾。
    • 中文示例:feat(ui): 新增暗黑模式切换按钮

第二部分:Body (选填)

对本次 commit 的详细描述。

  • 解释“为什么”:修改的动机是什么?解决了什么问题?
  • 解释“怎么做”:与之前的代码相比,主要区别是什么?(如果逻辑复杂)
  • 换行:每行建议不超过 72 个字符,避免在终端查看时自动换行错乱。

第三部分:Footer (选填)

用于追踪 issue 或重大变更。

  • Breaking Changes:如果不兼容旧版本,必须在此处(或 Header)注明 BREAKING CHANGE:,并说明迁移方案。这将触发语义化版本的 MAJOR 更新。
  • 关联 Issue:例如 Closes #123, Fixes #456

3. 深度剖析:实战中的常见误区与技巧

误区 1:万物皆 update

很多人的提交记录全是 update codefix bug

  • 深度分析:这等于没有写。fix bug 并没有告诉队友修复了哪个 bug。
  • 改进fix(login): 修复登录接口在 500 错误时未提示的问题

误区 2:一次提交包含过多修改

在一个 commit 里既修了 A 模块的 Bug,又加了 B 模块的新功能,还顺手改了 C 文件的缩进。

  • 深度分析:这破坏了提交的原子性。如果你需要回滚 B 功能,由于它们都在一个 commit 里,你会被迫回滚掉 A 的 Bug 修复。
  • 原则一个 Commit 只做一件事

误区 3:Scope 滥用或缺失

  • 深度分析:对于大型单体仓库(Monorepo),scope 至关重要。如果没有 scope,在看几千条 log 时很难过滤出“只看订单模块”的变更。

技巧:Emoji 的使用 (Gitmoji)

有些团队喜欢在 Type 前加 Emoji,虽然不在官方规范内,但能增加可视性:

  • :sparkles: -> New Feature
  • 🐛 :bug: -> Bug Fix
  • ♻️ :recycle: -> Refactor
  • (注意:正式的企业级开发或开源项目需谨慎使用,可能会干扰某些 changelog 工具)

4. 优秀的 Commit 示例

示例 1:新增功能

feat(blog): 添加文章点赞功能

为文章详情页增加了点赞按钮。
后端 API 已经更新,前端通过调用 /api/like 接口实现。
用户点赞后,按钮状态会即时更新并持久化。

示例 2:修复 Bug 并关闭 Issue

fix(utils): 修复 formatDate 在 Safari 下的兼容性问题

Safari 浏览器不支持 'YYYY-MM-DD' 格式的直接解析,会导致 Date 对象返回 Invalid Date。
改为使用 regex 手动分割字符串进行解析。

Closes #42

示例 3:破坏性更新 (Breaking Change)

feat(api)!: 重构用户数据结构,移除 age 字段

BREAKING CHANGE: api v2 返回的用户对象中不再包含 `age` 字段,请改用 `birthDate` 计算。

(注意:Header 中的 ! 也是标识 Breaking Change 的一种简写方式)

5. 如何强制落地?(工具链)

光靠口头约定很难坚持,通常需要工具辅助:

  1. Commitizen (cz-cli):一个撰写合格 Commit message 的工具。它会像向导一样一步步问你:类型是什么?范围是什么?描述是什么?然后自动生成符合规范的提交信息。
  2. Commitlint:结合 Husky 使用。在 git commit 时触发钩子,自动检查你的 message 是否符合规范。如果不符合,直接报错拒绝提交。
  3. Standard Version:自动根据 commit 记录升级版本号并生成 CHANGELOG.md

发表评论