Git提交信息规范
基于 Conventional Commits 标准的团队提交规范手册。详述 Header/Body/Footer 结构、Type/Scope 使用规则、正误对比与示例,并附 commitlint + husky 工具链配置及团队最佳实践,可直接作为项目提交规范落地执行。
0. 认识
0.1 类型与语义化版本对应关系
| 提交类型 | 语义化版本影响 |
|---|---|
feat | 次版本号 +1 |
fix | 修订号 +1 |
perf | 修订号 +1 |
BREAKING CHANGE | 主版本号 +1 |
| 其余类型 | 不影响版本号 |
0.2 快速查询速查表
# 新增功能 feat: xxx
# 修复Bug fix: xxx
# 文档修改 docs: xxx
# 格式调整 style: xxx
# 代码重构 refactor: xxx
# 性能优化 perf: xxx
# 测试相关 test: xxx
# 工程配置 chore: xxx
# CI/CD ci: xxx
# 回滚提交 revert: xxx1. 文档概述
1.1 规范目的
本规范基于业界通用的 Conventional Commits 1.0.0 标准制定,同时参考Angular社区成熟的提交约定,旨在统一团队Git提交信息的书写格式与语义标准,实现以下核心目标:
- 让提交历史具备结构化、高可读性,开发者可快速定位每次提交的核心意图与影响范围,降低代码回溯与问题排查成本
- 支撑自动化工具链解析,实现自动生成变更日志(CHANGELOG)、自动计算语义化版本号、自动化发布流程,减少人工整理成本
- 降低代码评审(Code Review)的理解成本,评审者可通过提交信息快速把握改动背景与核心逻辑,聚焦代码质量本身
- 沉淀项目演进知识,新人可通过规范的提交历史快速梳理项目发展脉络与技术决策背景,降低学习成本
1.2 适用范围
本规范适用于所有使用Git进行版本管理的项目,包括但不限于前端工程、后端服务、移动端应用、工具库/组件库、文档项目、算法项目等。 所有参与项目开发的人员,包括正式开发、外包、实习生、外部贡献者,提交代码至远程仓库时均需遵循本规范。
1.3 参考标准
- Conventional Commits 1.0.0 官方规范
- Angular Commit Message Guidelines
- 语义化版本 2.0.0 (Semantic Versioning)
- Git 官方文档 - 提交规范
1.4 为什么需要统一提交规范
在没有统一规范的团队中,提交历史往往存在大量无意义、模糊的内容,例如“修复bug”“更新代码”“调整”“优化一下”,这类提交会带来诸多痛点:
- 问题排查效率低:线上出现故障时,无法通过提交主题快速定位引入问题的提交,需要逐行查看代码diff,大幅增加排查时间
- 代码评审成本高:评审者无法第一时间理解改动的背景、目的与边界,需要反复沟通确认,拉长评审周期
- 版本发布困难:发版时需要人工逐个梳理提交内容,整理变更日志,耗时耗力且容易遗漏重要变更
- 知识传承断层:项目交接、新人入职时,混乱的提交历史无法体现项目的演进逻辑与技术决策过程,学习成本极高
- 自动化无法落地:非结构化的提交信息无法被工具解析,版本管理、发布流程只能依赖人工,效率低下且易出错
统一的提交规范本质是用极低的书写成本,换取团队长期的协作效率与项目可维护性提升。
1.5 规范设计原则
本规范在制定过程中遵循以下核心原则,兼顾严谨性与灵活性:
- 人机可读:提交信息既要让开发者快速看懂语义,也要能被自动化工具准确解析
- 最小结构:核心结构仅包含「头部-正文-页脚」三层,学习成本低,上手快
- 语义明确:每个类型、字段都有清晰的定义与边界,避免歧义与混用
- 可扩展:支持自定义影响范围、自定义页脚元数据,可根据不同团队、不同项目的需求适配
- 与版本对齐:提交类型直接对应语义化版本的变更规则,支撑自动化版本号计算
2. 提交信息完整结构
标准的约定式提交信息由三部分组成:头部(Header)、正文(Body)、页脚(Footer),各部分之间通过严格的空行分隔。 完整语法结构如下:
<类型>[可选 影响范围][!]: <简短描述>
[可选 正文]
[可选 页脚]2.1 头部(Header)
头部是提交信息的唯一必填部分,单行书写,是提交信息的核心摘要,包含三个字段:类型(type)、影响范围(scope)、简短描述(subject)。
2.1.1 格式约束
- 总长度建议不超过 72字符:该约定源自早期终端80字符的显示宽度,扣除Git日志自带的哈希占位、缩进后,72字符可保证在终端中单行完整显示,避免自动折行影响阅读
type与左括号之间无空格,右括号后紧跟冒号,冒号后必须有且仅有一个空格scope为可选字段,无明确影响范围时可省略括号部分,直接写<type>: <subject>- 包含破坏性变更时,可在范围后、冒号前增加
!标记,用于醒目提示不兼容变更
2.1.2 字段职责
- type:标识提交的性质与类别,从规定的枚举值中选择,是语义解析的核心依据
- scope:标识提交影响的业务模块、组件或范围,用于快速定位改动区域
- subject:提交内容的高度概括,一句话说明本次提交的核心改动
2.2 正文(Body)
正文是可选部分,用于详细描述本次提交的背景、改动逻辑、实现原理、注意事项等补充信息,是提交价值的重要载体。
2.2.1 格式约束
- 必须与头部之间间隔一个空行,否则Git会将其识别为头部的一部分
- 每行长度建议不超过72字符,超长内容主动换行,保证终端阅读体验
- 支持使用Markdown列表、分段等格式增强可读性,推荐使用无序列表梳理要点
- 正文内容可自由扩展,没有长度上限,但需简洁、有信息量,避免冗余
2.2.2 核心写作原则
正文重点说明「为什么改(Why)」,而非「改了什么(What)」。 代码diff可以直观展示所有改动的内容,但无法体现改动的动机、背景、技术选型的权衡过程、潜在的风险与注意事项——这些信息是项目的宝贵知识资产,也是提交正文的核心价值。半年后回溯代码时,正文能帮你快速理解当时的决策逻辑,避免重复踩坑。
2.3 页脚(Footer)
页脚是可选部分,用于标注破坏性变更、关联工单/Issue、回滚说明、协作信息等元数据,是自动化工具解析的重要依据。
2.3.1 格式约束
- 必须与正文之间间隔一个空行;无正文时,与头部之间间隔两个空行
- 每行脚注包含一个令牌(Token),后跟
:或#作为分隔符,再紧跟对应的值 - 令牌名称推荐使用连字符
-分隔单词(如Reviewed-by),BREAKING CHANGE是唯一例外,使用全大写空格分隔 - 页脚的值支持多行内容,后续行需保持缩进,直到下一个令牌出现为止
2.3.2 通用页脚字段
| 字段名 | 作用 | 示例 |
|---|---|---|
BREAKING CHANGE | 标记破坏性不兼容变更,对应语义化版本主版本号递增 | BREAKING CHANGE: 移除v1版本用户接口,不再兼容旧版SDK |
Closes / Fixes | 关联并自动关闭代码仓库的Issue/工单 | Closes #123, #456 |
Refs | 引用相关Issue/文档,但不关闭 | Refs #789 |
Reverts | 标记本次提交为回滚操作,指明被回滚的提交哈希 | Reverts: 7a3f2d9c |
Reviewed-by | 标注代码评审人 | Reviewed-by: 张三 <zhangsan@example.com> |
Co-authored-by | 标注共同作者,用于多人协作的提交 | Co-authored-by: 李四 <lisi@example.com> |
Signed-off-by | 签署开发者原创声明(DCO),开源项目常用 | Signed-off-by: 王五 <wangwu@example.com> |
3. 类型前缀(Type)全解析
type 用于标识本次提交的核心性质,必须从规定的枚举值中选择,统一使用小写英文,不得自定义未约定的类型。
3.1 核心类型详解
3.1.1 feat:新增功能
- 定义:面向产品用户、面向外部调用者的新增功能、新增特性、新增API,对应语义化版本的 次版本号(MINOR) 递增
- 判定标准:用户可感知到新的能力;对外暴露的接口新增了方法/字段
- 适用场景:
- 新增用户注册、登录等业务功能
- 新增数据导出、报表生成等产品能力
- 新增对外API接口、新增SDK方法
- 新增页面、新增组件、新增配置项
- 反例:
- 修复功能bug不算feat,属于fix
- 新增内部工具函数、不对外暴露的辅助方法不算feat
- 重构现有功能、没有新增能力不算feat
3.1.2 fix:修复问题
- 定义:修复面向用户的Bug、逻辑错误、功能异常,对应语义化版本的 修订号(PATCH) 递增
- 判定标准:现有功能与预期不符,修复后回归正确行为
- 适用场景:
- 修复登录态失效、订单状态不同步等业务bug
- 修复页面样式错乱、交互异常等前端问题
- 修复接口报错、数据计算错误等后端问题
- 修复兼容性问题、边界场景异常
- 反例:
- 代码格式调整、缩进修改不算fix
- 重构代码逻辑、行为没有变化不算fix
- 修复测试用例、修复文档错误不算fix
3.1.3 docs:文档变更
- 定义:仅修改文档、注释类内容,不影响任何业务代码与运行逻辑
- 判定标准:代码行为完全不变,仅修改文字说明类内容
- 适用场景:
- 更新README.md、项目说明文档、部署文档
- 修改API接口文档、使用手册、开发规范
- 补充、修改代码注释
- 修改CHANGELOG、版本说明
- 反例:
- 修改代码逻辑顺带修改注释,以主改动为准,不算docs
- 修改代码中的文案、提示语,属于业务改动,不算docs
3.1.4 style:代码格式调整
- 定义:不改变代码逻辑、不影响功能的格式类、风格类调整,仅影响代码外观
- 判定标准:代码编译、运行后的行为完全不变,只是排版、格式、命名风格变化
- 适用场景:
- 调整代码缩进、空格、换行、分号补全
- 按照ESLint/Prettier规范格式化代码
- 修改变量命名风格(如统一驼峰命名)、调整代码顺序
- 移除多余空行、补充收尾空行
- 反例:
- 修改CSS业务样式、UI视觉效果不算style,属于feat或fix
- 修改变量名导致逻辑变化、重构代码结构不算style
3.1.5 refactor:代码重构
- 定义:既不新增功能、也不修复Bug的代码结构/逻辑改动,不改变对外的行为与接口
- 判定标准:外部功能完全不变,内部实现优化、结构调整、代码质量提升
- 适用场景:
- 抽离公共工具函数、公共组件,消除重复代码
- 重构代码结构、拆分大函数/大组件、优化模块划分
- 重命名变量、函数、类,提升代码可读性
- 替换技术实现方案(如用Map替换对象),但行为不变
- 移除废弃的冗余代码
- 反例:
- 新增功能不算refactor
- 修复bug不算refactor
- 专门的性能优化不算refactor,归为perf
3.1.6 perf:性能优化
- 定义:专门用于提升运行性能的提交,属于refactor的一个特殊子类,对应语义化版本的 修订号(PATCH) 递增
- 判定标准:有明确的性能收益,如加载速度提升、内存占用降低、响应时间缩短
- 适用场景:
- 优化图片加载、资源压缩,提升页面加载速度
- 优化算法时间复杂度、减少循环次数
- 优化接口响应速度、减少数据库查询
- 降低内存占用、修复内存泄漏
- 反例:
- 普通代码重构、没有明确性能收益不算perf
- 功能改动带来的附带性能提升不算perf
3.1.7 test:测试相关
- 定义:新增、修改测试用例与测试相关代码,不影响业务功能
- 判定标准:仅改动测试代码,业务代码完全不变
- 适用场景:
- 新增单元测试、集成测试、E2E测试用例
- 修改测试用例、更新测试Mock数据
- 调整测试配置、测试框架、测试脚本
- 补充测试覆盖率
- 反例:
- 修复业务bug导致测试用例同步修改,以主改动为准,不算test
- 测试环境的业务代码调试不算test
3.1.8 chore:工程/工具变更
- 定义:构建流程、依赖管理、脚手架配置等工程化改动,不影响业务代码与用户功能
- 判定标准:对业务功能、产品逻辑完全无影响,属于工程基建类改动
- 适用场景:
- 升级/降级npm/maven等依赖包
- 修改webpack/vite/rollup等构建工具配置
- 修改.gitignore、.eslintrc等工程配置文件
- 修改项目构建脚本、发布脚本
- 调整项目目录结构(不涉及业务逻辑变动)
- 反例:
- 业务代码的配置项修改不算chore
- CI/CD流水线配置不算chore,归为ci
3.1.9 ci:CI/CD相关
- 定义:持续集成、持续部署流程的配置变更,属于chore的一个特殊子类
- 判定标准:仅修改CI/CD相关的配置与脚本
- 适用场景:
- 修改GitHub Actions、GitLab CI、Jenkins流水线配置
- 修改Docker构建脚本、镜像配置
- 调整自动化测试、自动化发布流程
- 修改CI环境变量、执行步骤
- 反例:
- 本地构建脚本修改不算ci,归为chore
- 业务代码的部署配置不算ci
3.1.10 revert:回滚提交
- 定义:撤销之前的某一次或多次提交,回滚代码变更
- 判定标准:通过
git revert命令生成的回滚提交,手动修改代码回退不算 - 规范格式:
revert: 回滚"feat: 新增文章评论功能" Reverts: 7a3f2d9c 原因:评论功能上线后出现性能问题,临时回滚优化 - 注意:回滚多个提交时,需在页脚中列出所有被回滚的提交哈希,并说明回滚原因
3.2 易混淆类型对比
| 场景 | 正确类型 | 错误类型 | 说明 |
|---|---|---|---|
| 修改CSS样式,优化按钮显示效果 | feat/fix | style | style仅指代码格式,业务样式改动属于功能范畴 |
| 抽离公共工具函数,优化代码复用 | refactor | feat | 没有新增用户可感知的功能,属于代码重构 |
| 升级Vue版本,兼容原有代码 | chore | refactor | 依赖升级属于工程化改动,不涉及业务逻辑重构 |
| 修复ESLint报错,调整代码格式 | style | fix | 代码规范问题不属于业务bug,属于格式调整 |
| 优化接口查询速度,减少响应时间 | perf | refactor | 有明确性能收益的优化,优先归为perf |
| 修改Jenkins流水线构建步骤 | ci | chore | 持续集成相关的专属类型,优先用ci |
| 修改README中的接口文档 | docs | chore | 文档类改动专属类型,优先用docs |
3.3 类型与语义化版本对应关系
| 提交类型 | 语义化版本影响 | 说明 |
|---|---|---|
feat | 次版本号 +1(MINOR) | 新增功能,向前兼容 |
fix | 修订号 +1(PATCH) | 修复bug,向前兼容 |
perf | 修订号 +1(PATCH) | 性能优化,向前兼容 |
包含 BREAKING CHANGE | 主版本号 +1(MAJOR) | 破坏性变更,不向前兼容 |
docs/style/refactor/test/chore/ci/revert | 不影响版本号 | 不涉及用户功能变更 |
4. 影响范围(Scope)命名指南
scope 用于标明本次改动影响的业务模块/组件,为可选字段,用于帮助开发者快速定位改动区域,尤其适合中大型项目。
4.1 命名原则
- 业务优先:优先按业务模块划分,而非技术分层,例如
user(用户模块)、order(订单模块),而非api、utils - 保持统一:同一模块的命名在项目内保持唯一,避免出现
user/User/user-center多种写法 - 粒度适中:范围不要太泛(如
common几乎等于没写),也不要太细(如login-button),以模块/组件级别为宜 - 跨模块处理:改动涉及多个模块时,若有主次则按主模块命名;若为全局改动,可使用
*或直接省略scope
4.2 层级划分
对于复杂项目,可支持层级化scope,用斜杠 / 或连字符 - 分隔父子模块,团队内统一格式即可。 示例:
user/auth:用户模块下的认证子模块order/payment:订单模块下的支付子模块components/button:组件库下的按钮组件
4.3 不同项目类型的命名建议
4.3.1 前端单页应用
- 业务模块:
user、order、goods、cart、home - 基础能力:
router、store、utils、components、styles、assets - 工程相关:
build、deploy、env
4.3.2 后端微服务项目
- 服务维度:
user-service、order-service、gateway - 公共组件:
common、db、redis、mq - 基础设施:
config、log、monitor
4.3.3 Monorepo多包项目
直接使用包名作为scope,例如:
@project/components@project/utils@project/cli
4.3.4 移动端应用
- 页面维度:
page-home、page-mine - 原生能力:
native-device、native-push - 公共组件:
components、utils
4.4 常用示例
feat(auth): 新增短信验证码登录功能
fix(order): 修复订单支付状态不同步问题
refactor(utils): 重构日期格式化工具函数
docs(api): 更新用户模块接口文档
perf(goods): 优化商品列表加载速度
ci(deploy): 调整生产环境部署流程5. 简短描述(Subject)书写规范
subject 是对本次提交的高度概括,一句话说明改动内容,是头部的核心组成部分,决定了提交信息的第一可读性。
5.1 核心规则
- 祈使语气:使用祈使句开头,描述提交“会做什么”,而非“做了什么”。中文使用动词原形开头,如「新增、修复、优化、调整、重构、升级、移除、更新」;英文使用动词原形,如「add、fix、optimize、refactor、remove」
- 简洁明确:长度控制在50字符以内,一眼可读,不堆砌细节,细节放在正文
- 结尾无标点:末尾不加句号、感叹号、分号等标点符号
- 信息完整:包含「改动对象 + 动作 + 结果」,避免模糊表述
- 语言统一:团队内统一使用中文或英文,避免中英文混杂
5.2 正误对比
| 错误示例 | 正确示例 | 错误原因 |
|---|---|---|
| fix: 修复了一些bug | fix: 修复登录页密码输入框无法输入中文 | 描述模糊,无具体信息,无法定位问题 |
| feat: 新增评论功能,还加了点赞和收藏,优化了列表样式 | feat: 新增文章评论与点赞功能 | 过长,超出长度限制,堆砌多个改动 |
| style: 调整了代码缩进。 | style: 统一全局代码缩进为2空格 | 结尾带句号,描述不够精准 |
| refactor: 重构了一下工具函数,大概改了点东西 | refactor: 抽离通用日期格式化工具函数 | 口语化,表述不专业,无有效信息 |
| fix: 我把订单的bug修好了 | fix: 修复订单创建时金额计算错误 | 第一人称表述,不符合祈使语气规范 |
| feat: 超级好用的新功能上线啦 | feat: 新增订单批量导出功能 | 情绪化表述,不专业,没有说明具体内容 |
5.3 常用动词速查表
| 类别 | 常用动词 |
|---|---|
| 新增类 | 新增、添加、增加、引入、支持、上线 |
| 修复类 | 修复、解决、修复、修正、恢复 |
| 优化类 | 优化、提升、改进、改善、精简、加速 |
| 重构类 | 重构、抽离、拆分、整合、重写、调整 |
| 删除类 | 移除、删除、废弃、清理、下线 |
| 更新类 | 更新、升级、降级、修改、调整 |
| 文档类 | 更新、补充、完善、修正、编写 |
| 格式类 | 统一、格式化、调整、修正 |
6. 正文(Body)结构化写作指南
对于简单改动,可省略正文;对于核心功能、复杂Bug修复、架构调整、破坏性变更,必须补充完整正文,说明改动的来龙去脉。
6.1 推荐四段式结构
标准正文建议包含以下四个部分,可根据实际场景裁剪:
(1)背景与动机
为什么要做这次改动?解决了什么问题?需求来源是什么?
- Bug修复类:说明问题现象、影响范围、根因分析
- 功能新增类:说明需求背景、用户价值、要达成的目标
- 重构/优化类:说明现有方案的痛点、优化的必要性
(2)实现方案
核心思路是什么?采用了什么技术方案?关键逻辑是什么?
- 说明整体实现流程、核心改动点
- 对比不同方案的权衡,说明选择当前方案的原因
- 标注关键的技术细节、注意事项
(3)影响范围
改动涉及哪些模块?哪些功能会受影响?有没有副作用?
- 明确影响的业务范围、代码范围
- 说明是否有兼容性问题、是否需要同步修改其他模块
- 标注风险点、需要重点测试的场景
(4)后续计划与备注
有没有遗留问题?后续优化方向是什么?其他需要说明的事项。
6.2 不同场景的写作模板
6.2.1 Bug修复类
fix(order): 修复高并发下订单状态重复更新问题
- 背景:高并发场景下,支付回调多次触发,导致订单状态被重复更新,出现库存扣减异常
- 根因:回调接口未做幂等校验,状态流转没有前置校验,并发请求可同时修改同一订单
- 方案:基于Redis实现回调接口幂等校验,增加订单状态机流转校验,非法状态直接拦截
- 影响:仅影响支付回调流程,不涉及订单创建、退款、发货等其他链路
- 备注:测试环境需配置Redis集群验证幂等效果,压测1000并发无异常6.2.2 功能新增类
feat(export): 新增订单数据批量导出功能
- 背景:运营同学需要按时间范围导出订单数据做分析,目前只能手动逐条复制,效率极低
- 方案:
1. 后端支持按时间范围、订单状态筛选导出Excel
2. 大文件采用分片下载 + 异步生成方式,避免浏览器超时
3. 导出记录留存7天,支持重复下载
- 权限:仅管理员、运营角色可使用导出功能,普通用户无权限
- 影响:新增导出接口,不影响现有订单相关功能
- 后续:下个版本支持自定义导出字段、支持导出CSV格式6.2.3 代码重构类
refactor(utils): 重构通用请求工具函数
- 背景:现有请求工具函数封装混乱,错误处理逻辑分散在各个业务代码中,维护成本高
- 方案:
1. 统一封装请求拦截、响应拦截、错误处理逻辑
2. 统一错误码提示、异常上报、重试机制
3. 兼容原有调用方式,逐步替换旧的调用
- 影响:所有使用请求工具的模块,行为完全兼容,无功能变更
- 风险:部分特殊场景的错误处理可能有差异,需重点测试文件上传、下载场景6.2.4 性能优化类
perf(goods): 优化商品列表首屏加载速度
- 背景:商品列表页数据量大,首屏加载平均耗时3.2s,用户体验差
- 优化目标:首屏加载时间降至1.5s以内
- 方案:
1. 接口分页查询,首屏只加载第一页数据
2. 图片懒加载,可视区域外图片延迟加载
3. 接口数据缓存,5分钟内重复访问直接读缓存
- 效果:首屏加载时间平均降至1.3s,提升约59%
- 影响:仅优化加载逻辑,商品列表功能、交互完全不变6.3 写作避坑
- 不要逐行复述代码:正文不是代码的文字翻译,不要把每行代码做了什么都写出来,重点讲思路与逻辑
- 不要只写“做了什么”:重点补充“为什么这么做”,这是diff看不到的信息,也是正文的核心价值
- 不要太长:正文是摘要,不是论文,控制在3-5个要点为宜,过长的文档可以链接到需求文档、设计文档
- 不要模糊表述:避免“大概、可能、应该、差不多”这类不确定的表述,准确描述改动内容与影响
7. 页脚(Footer)元数据规范
7.1 破坏性变更(BREAKING CHANGE)
当提交包含不兼容的API变更、架构调整、配置废弃时,必须标注破坏性变更,对应语义化版本的 主版本号(MAJOR) 递增。
7.1.1 判定标准
只要满足以下任意一条,即为破坏性变更:
- 对外API接口签名修改、参数删除/重命名、返回值结构变更
- 配置项删除、默认值修改、配置格式变更,导致原有配置失效
- 核心依赖大版本升级,且不向下兼容
- 数据库表结构变更,不兼容历史数据
- 面向用户的功能正式下线、移除
- 公共组件/工具函数的API变更,调用方必须修改代码才能升级
7.1.2 书写规范
refactor(api): 统一用户认证接口响应结构
BREAKING CHANGE: 重构用户认证接口,移除旧版token校验逻辑,不再兼容v1版本SDK
- 变更说明:所有接口响应移除外层code/message包裹,直接返回业务数据,状态通过HTTP状态码标识
- 迁移方案:
1. 调用方升级至v2版本SDK
2. 请求头新增 X-App-Version: 2.0 字段
3. 适配新的响应结构与错误处理逻辑
- 兼容周期:旧版接口保留3个月,2024年12月31日正式下线
- 相关文档:docs/api-migration-v2.md7.1.3 ! 标记用法
可在 type(scope) 后增加 ! 标记,醒目提示破坏性变更,用于快速识别。 使用 ! 后,页脚仍建议补充详细的 BREAKING CHANGE 说明。 示例:
feat(api)!: 重构用户认证接口v2版本
BREAKING CHANGE: ......7.2 关联Issue/工单
通过 Closes、Fixes、Resolves 关键字关联代码仓库的Issue,提交合并到主干后会自动关闭对应Issue。
- 单个Issue:
Closes #123 - 多个Issue:
Closes #123, #456, #789 - 习惯区分:
Fixes多用于修复Bug的Issue,Closes多用于功能需求、任务类Issue,团队可统一约定
若仅引用相关Issue、不需要关闭,使用 Refs 关键字: Refs #999, 相关需求文档链接
7.3 回滚提交
使用 git revert 回滚提交时,标准页脚需包含 Reverts 字段,指明被回滚的提交哈希,多个提交用逗号分隔。 示例:
revert: 回滚"feat: 新增文章评论功能"
Reverts: 7a3f2d9c, b4d2e8f1
原因:评论功能上线后引发数据库性能问题,临时回滚优化,预计3天后重新上线7.4 协作元数据
7.4.1 共同作者
多人协作完成的提交,可通过 Co-authored-by 标注所有共同作者,贡献会统计到对应作者的GitHub/GitLab账号。 格式:Co-authored-by: 姓名 <邮箱> 示例:
feat(user): 新增用户中心头像上传功能
Co-authored-by: 张三 <zhangsan@example.com>
Co-authored-by: 李四 <lisi@example.com>7.4.2 评审人
标注代码评审人员,用于追溯评审责任。 格式:Reviewed-by: 姓名 <邮箱>
7.4.3 测试人
标注测试负责人,确认测试通过。 格式:Tested-by: 姓名 <邮箱>
7.5 自定义扩展
团队可根据自身需求自定义页脚字段,例如:
Task: TASK-1234:关联内部项目管理系统的任务编号Doc: docs/xxx.md:关联相关文档Changelog: 新增用户头像上传功能:自定义CHANGELOG显示内容Breaking: 是/否:快速标记是否破坏性变更
自定义字段建议统一命名规范,方便后续工具解析。
8. 完整场景示例集合
8.1 极简提交(仅头部)
适用于小改动、简单修复,日常开发高频使用。
feat: 新增页面返回顶部按钮fix: 修复手机号正则校验错误docs: 更新README项目介绍style: 统一首页代码缩进格式chore: 升级lodash依赖至4.17.21版本8.2 带影响范围的提交
feat(auth): 新增第三方微信登录fix(cart): 修复购物车商品数量加减异常refactor(router): 优化路由懒加载配置perf(goods): 优化商品列表图片加载速度8.3 带正文的完整功能提交
feat(export): 新增订单数据批量导出功能
- 支持按时间范围、订单状态筛选导出Excel格式
- 大文件采用分片下载,避免浏览器内存溢出与超时
- 导出记录留存7天,支持重复下载与状态查询
- 权限控制:仅管理员与运营角色可使用导出功能
Closes #898.4 复杂Bug修复提交
fix(payment): 修复高并发下支付回调重复通知问题
- 现象:高并发场景下,支付平台多次回调,导致订单状态重复更新,库存重复扣减
- 根因:回调接口未做幂等校验,状态流转无前置校验,并发请求可同时修改同一订单
- 方案:基于Redis实现回调接口幂等校验,增加订单状态机流转前置校验
- 影响:仅影响支付回调流程,不涉及订单创建、退款等其他链路
- 验证:压测1000并发无重复更新,测试环境验证通过
Fixes #1128.5 含破坏性变更的提交
refactor(api): 统一用户模块接口响应结构
- 移除所有接口外层code/message包裹结构
- 统一通过HTTP状态码标识请求成功/失败
- 错误信息统一放入error字段,业务数据直接返回
- 统一分页字段命名为total/list
BREAKING CHANGE: 所有用户模块接口响应结构变更,前端调用必须适配
- 迁移步骤:
1. 移除接口响应的外层data解构
2. 适配HTTP状态码的错误处理逻辑
3. 分页字段替换为total与list
- 兼容周期:旧版接口保留3个月,2024年12月31日下线
- 详细文档:docs/api/user-migration-v2.md
Closes #2018.6 回滚提交
revert: 回滚"feat: 新增文章评论功能"
Reverts: 7a3f2d9cb4e6d3f2a1b0c5d8e9f0a1b2c3d4e5f
原因:评论功能上线后引发数据库慢查询,导致首页响应超时,临时回滚优化
预计重新上线时间:2024-06-208.7 多人协作提交
feat(user): 新增个人中心资料编辑功能
- 支持修改头像、昵称、个人简介
- 支持修改绑定手机号与邮箱
- 增加敏感操作二次验证
Co-authored-by: 张三 <zhangsan@example.com>
Co-authored-by: 李四 <lisi@example.com>
Reviewed-by: 王五 <wangwu@example.com>
Closes #768.8 CI/CD配置修改
ci: 优化生产环境构建部署流程
- 增加构建缓存,缩短构建时间约40%
- 增加部署前自动化测试校验,测试不通过禁止发布
- 增加灰度发布步骤,支持按比例切流
- 新增部署失败自动回滚机制9. 常见错误与避坑指南
9.1 格式类错误
| 错误写法 | 正确写法 | 说明 |
|---|---|---|
Feat: 新增功能 | feat: 新增功能 | type必须全小写 |
feat:新增功能 | feat: 新增功能 | 冒号后必须加一个空格 |
feat (user): 新增功能 | feat(user): 新增功能 | type与括号之间不能有空格 |
feat(user):修复bug | feat(user): 修复bug | 冒号后必须加空格 |
feat( User ): 新增功能 | feat(user): 新增功能 | scope内不能有空格 |
| 头部后直接写正文,没空行 | 头部与正文之间空一行 | 空行是结构分隔的标识,不能省略 |
9.2 内容类错误
9.2.1 类型混用
- 把业务样式修改写成
style:CSS样式是业务功能的一部分,修改样式属于feat或fix,style仅指代码格式 - 把依赖升级写成
feat:普通依赖升级属于工程化改动,归为chore;只有依赖升级带来了明确的新功能,且新功能是本次提交的核心,才用feat - 把重构写成
fix:重构不改变外部行为,没有修复bug,不能用fix - 把测试用例补充写成
test但同时改了业务代码:以主改动为准,测试代码只是配套修改,不能用test类型
9.2.2 描述模糊
避免以下无信息量的描述:
- “修复了一些问题”、“优化了代码”、“调整了样式”
- “更新一下”、“改了点东西”、“临时提交”
- “修复bug”、“优化性能”、“重构代码”
好的描述应该精准、具体,让人一眼知道改了什么地方、什么内容。
9.2.3 提交粒度过大
一个提交包含多个不相关的改动,比如“新增登录功能 + 修复订单bug + 优化首页样式 + 更新依赖”,俗称“大杂烩提交”。
- 危害:无法回滚单个功能;无法快速定位问题;代码评审困难;提交历史混乱
- 原则:一个提交只做一件事,不同类型、不同模块的改动尽量拆分提交
- 技巧:开发过程中随时小步提交,合并到主干前通过
git rebase -i整理提交历史
9.2.4 提交粒度过细
反过来,也不要拆得太碎,比如改一个错别字提交一次、补一个分号提交一次,过于零散的提交同样会让历史变得混乱。 建议:同类型、同范围的小改动可以合并成一个提交。
9.3 认知类误区
9.3.1 “提交规范是形式主义,没用”
短期看,写规范的提交信息会多花十几秒,但长期来看:
- 排查线上问题时,通过提交历史快速定位引入点,节省几小时甚至几天
- 代码评审时,快速理解改动背景,减少反复沟通
- 新人接手项目时,通过提交历史梳理演进脉络,降低学习成本
- 自动化生成CHANGELOG、自动版本号,减少发版工作量
提交规范是典型的“短期投入小、长期收益大”的团队协作规范。
9.3.2 “我自己的分支,随便写没关系”
个人开发分支可以临时提交(如WIP),但合并到公共分支(develop、main、master)前,必须整理成规范的提交。 公共分支的提交历史是项目的公共资产,不是个人的记事本,要对所有协作者负责。
9.3.3 “小改动不用讲规范”
规范是统一的习惯,不分大小改动。越是小改动,写规范的成本越低,收益越高。 如果所有小改动都不遵守规范,积累下来提交历史依然会混乱不堪。
10. 自动化工具链配置指南
手动遵守规范依赖人的自觉性,容易出错,推荐通过工具链强制校验,降低心智负担,保证规范落地。
10.1 工具链全景
| 工具 | 作用 |
|---|---|
| Husky | Git钩子工具,在commit前、提交信息时触发校验 |
| commitlint | 校验提交信息是否符合规范,不符合则拦截 |
| cz-git + Commitizen | 交互式提交工具,引导式生成规范提交信息,不用记规则 |
| lint-staged | 只校验暂存区的文件,配合ESLint/Prettier做代码格式化 |
| standard-version | 基于提交历史自动生成CHANGELOG、自动计算版本号 |
10.2 Husky + commitlint 强制校验
10.2.1 安装依赖
npm install -D @commitlint/cli @commitlint/config-conventional husky10.2.2 初始化Husky
# 初始化husky
npx husky install
# 配置package.json脚本,npm install后自动初始化husky
npm set-script prepare "husky install"10.2.3 添加commit-msg钩子
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"10.2.4 创建commitlint配置文件
项目根目录新建 commitlint.config.js:
module.exports = {
// 继承官方约定式提交规范
extends: ['@commitlint/config-conventional'],
// 自定义规则
rules: {
// type类型枚举,可根据团队需求增减
'type-enum': [
2, // 0: 关闭, 1: 警告, 2: 错误
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'chore',
'ci',
'revert'
]
],
// type小写
'type-case': [2, 'always', 'lower-case'],
// type不能为空
'type-empty': [2, 'never'],
// subject不能为空
'subject-empty': [2, 'never'],
// subject最大长度50
'subject-max-length': [2, 'always', 50],
// 正文每行最大长度72
'body-max-line-length': [2, 'always', 72],
// 冒号后必须有空格
'colon-space': [2, 'always'],
// scope用括号包裹,中间无空格
'scope-case': [2, 'always', 'lower-case']
}
};10.2.5 效果
配置完成后,提交信息不符合规范时,会直接拦截并报错,提示具体哪里不符合,修正后才能提交成功。 示例报错:
⧗ input: 修复登录bug
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint10.3 cz-git 交互式提交
对于不熟悉规范的成员,可配置交互式提交工具,通过选择的方式生成规范的提交信息,零学习成本。
10.3.1 安装依赖
npm install -D cz-git commitizen10.3.2 配置package.json
{
"scripts": {
"commit": "git-cz"
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
}10.3.3 自定义配置(可选)
在 commitlint.config.js 中增加自定义提示配置,支持中文:
module.exports = {
extends: ['@commitlint/config-conventional'],
// 提示配置
prompt: {
// 中文提示
messages: {
type: '选择你要提交的类型 :',
scope: '选择一个影响范围 (可选):',
customScope: '输入自定义的影响范围:',
subject: '简短描述本次变更:\n',
body: '详细描述本次变更 (可选). 使用 "|" 换行:\n',
breaking: '列出破坏性变更 (可选):\n',
footerPrefixsSelect: '选择关联的Issue类型 (可选):',
customFooterPrefixs: '输入自定义前缀:',
confirmCommit: '确认提交以上信息?'
},
// 自定义类型选项
types: [
{ value: 'feat', name: 'feat: 新增功能', emoji: '✨' },
{ value: 'fix', name: 'fix: 修复Bug', emoji: '🐛' },
{ value: 'docs', name: 'docs: 文档变更', emoji: '📝' },
{ value: 'style', name: 'style: 代码格式', emoji: '💄' },
{ value: 'refactor', name: 'refactor: 代码重构', emoji: '♻️' },
{ value: 'perf', name: 'perf: 性能优化', emoji: '⚡' },
{ value: 'test', name: 'test: 测试相关', emoji: '✅' },
{ value: 'chore', name: 'chore: 工程配置', emoji: '🔧' },
{ value: 'ci', name: 'ci: CI/CD', emoji: '🚀' },
{ value: 'revert', name: 'revert: 回滚提交', emoji: '⏪' }
],
// 自定义scope选项
scopes: [
{ name: 'user', description: '用户模块' },
{ name: 'order', description: '订单模块' },
{ name: 'goods', description: '商品模块' },
{ name: 'utils', description: '工具函数' },
{ name: 'components', description: '公共组件' }
],
// 是否开启emoji
useEmoji: true,
// subject长度限制
subjectLimit: 50
},
rules: {
// ... 原有规则
}
};10.3.4 使用方式
代替 git commit 命令,执行:
npm run commit然后按照提示一步步选择类型、范围、输入描述,自动生成符合规范的提交信息。
10.4 自动生成CHANGELOG与版本号
通过 standard-version 工具,基于规范的提交历史,自动计算语义化版本号、生成CHANGELOG文件。
10.4.1 安装
npm install -D standard-version10.4.2 配置package.json脚本
{
"scripts": {
"release": "standard-version",
"release:major": "standard-version --release-as major",
"release:minor": "standard-version --release-as minor",
"release:patch": "standard-version --release-as patch"
}
}10.4.3 使用
# 自动根据提交历史计算版本号,生成CHANGELOG,打tag
npm run release
# 手动指定升级主版本号
npm run release:major执行后会自动:
- 读取提交历史,根据feat/fix/BREAKING CHANGE计算版本号
- 更新package.json中的version字段
- 生成CHANGELOG.md文件,记录每个版本的变更
- 自动提交变更并打上git tag
10.5 CI流水线校验
为了防止有人绕过本地钩子提交不规范的代码,建议在CI流水线中增加提交信息校验。 以GitHub Actions为例,在 .github/workflows/commitlint.yml 中配置:
name: Commitlint
on: [pull_request]
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v5这样提交信息不规范的PR会直接校验失败,无法合并。
11. 团队落地最佳实践
11.1 落地步骤
第一步:达成共识
- 团队一起讨论规范,确认类型、scope、规则,达成一致意见
- 说明规范的价值与好处,让大家理解为什么要做,而不是强行推行
- 给出完整的文档、示例、速查表,降低学习成本
第二步:工具兜底
- 先上自动化工具,husky + commitlint 强制校验,从技术上保证规范落地
- 配置cz-git交互式提交,降低学习门槛,新人也能快速上手
- 工具配置由专人维护,避免每个人都要搭环境
第三步:逐步推行
- 不用一开始就100%严格,先保证格式正确,再逐步提升内容质量
- 新功能、新模块优先遵守,历史代码逐步整改
- 前1-2周安排专人review提交信息,及时纠正不规范写法
第四步:持续优化
- 定期回顾提交规范的执行情况,收集团队反馈
- 根据项目特点调整规则,比如增加自定义type、自定义scope
- 不断优化工具链配置,提升开发体验
11.2 不同规模团队的适配
小型团队(3-5人)
- 规则从简,核心保证type + subject规范,body不做强制要求
- scope可以不用,项目小模块少,通过subject就能定位
- 工具简单配置,强制校验基础格式
- 重点是统一习惯,保持历史干净
中型团队(10-20人)
- 完整推行规范,type、scope、subject、body、footer全量要求
- 明确scope命名规范,对齐业务模块
- 核心功能、复杂改动必须写正文
- 配置完整工具链,强制校验 + 交互式提交
- 代码评审时同步评审提交信息
大型团队/开源项目
- 严格执行规范,提交信息作为PR准入条件
- 详细的贡献者文档,说明提交规范
- CI流水线强制校验,不规范的PR无法合并
- 配备自动化发布流程,基于提交信息生成版本与CHANGELOG
- 定期清理不规范的提交历史
11.3 与分支策略配合
Feature开发分支
- 开发过程中可以频繁提交,允许WIP(工作进行中)类的临时提交
- 不用每次都写得非常规范,保证开发效率
- 提交粒度小,方便随时回退、保存进度
合并到公共分支前
- 通过
git rebase -i整理提交历史,把零散的提交合并成规范的、有意义的提交 - 删掉WIP、临时提交、修复上一个提交的小bug这类无意义提交
- 保证公共分支的每一个提交都是原子的、规范的、可追溯的
- 推荐使用Squash Merge(压缩合并),把整个PR的所有提交压缩成一个规范的提交合入主干
主干分支
- 主干分支(main/master)的提交历史必须100%符合规范
- 每一个提交对应一个功能、一个修复、一个改动,清晰可追溯
- 禁止直接向主干提交不规范的代码
11.4 代码评审要点
提交信息是代码评审的一部分,评审代码的同时也要评审提交信息:
- 格式是否规范:type、scope、subject是否符合要求
- 类型是否准确:有没有类型混用的情况
- 描述是否清晰:能不能一眼看懂改了什么
- 粒度是否合适:有没有一个提交混了多个不相关的改动
- 正文是否充分:复杂改动有没有说明背景、方案、影响
- 关联是否完整:有没有关联对应的Issue、任务
不规范的提交要求修改后再合并,逐步培养团队的规范意识。
11.5 新人引导
- 把提交规范加入新人入职文档,作为必看内容
- 提供速查表、模板、示例,方便新人查阅
- 配置交互式提交工具,降低新人上手门槛
- 导师带教期间,检查新人的提交信息,及时纠正
- 前几次提交允许不完美,逐步引导,不用一上来就卡死
12. 常见问题FAQ
Q1:一次提交包含多个类型的改动怎么办?
A:优先按核心改动确定type,比如主要是加功能,顺便改了格式,就用feat。 但更推荐拆分提交:把不同类型的改动拆成多个独立提交,比如格式调整单独一个style提交,功能改动单独一个feat提交。拆分后提交历史更清晰,也方便单独回滚。
Q2:已经提交了但还没推送,怎么修改提交信息?
A:如果是最近一次提交,执行 git commit --amend,进入编辑器修改提交信息,保存退出即可。 如果是历史提交,用交互式变基:git rebase -i <提交哈希>,把要修改的提交前的pick改成r,保存后依次修改每个提交的信息。
Q3:已经推送到远程的不规范提交怎么办?
A:如果是个人分支,没人基于你的分支开发,可以修改后强制推送:git push --force-with-lease。 如果是公共分支、已经有人合入了,不建议修改历史,会影响其他人的代码,后续提交注意规范即可。不要为了规范破坏协作。
Q4:WIP(开发中)的提交怎么写?
A:个人开发分支可以用 wip: xxx 作为临时提交,比如 wip: 用户中心开发中。 注意:WIP提交只能留在个人分支,合并到公共分支前必须清理掉,整理成规范的提交。 如果团队需要正式支持WIP类型,可以在commitlint配置的type-enum中增加wip。
Q5:修复上一个提交的小bug,怎么提交?
A:如果还没推送,建议直接用 git commit --amend 追加到上一个提交里,保持历史干净。 如果已经推送了,单独提交的话,用对应类型,比如fix,描述清楚修复的内容。不要写“修复上一个提交的bug”这种无意义描述。
Q6:中文还是英文?
A:根据团队情况选择,国内团队优先中文,保证所有人都能快速看懂。开源项目、国际化团队用英文。 核心是统一,不要一会儿中文一会儿英文,更不要中英文混杂在同一个subject里。
Q7:第三方依赖升级用什么类型?
A:普通的依赖版本升级,不影响业务功能,用 chore。 如果是大版本升级,有破坏性变更,或者为了支持新功能升级依赖,建议单独一个chore提交升级依赖,再一个feat提交开发新功能。 不要把依赖升级和业务代码改在同一个提交里。
Q8:删除废弃的代码/功能用什么类型?
A:如果是删除面向用户的功能、对外暴露的API,属于破坏性变更,用 feat! 或 refactor!,标注BREAKING CHANGE。 如果是删除内部废弃代码、用户无感知的清理,用 refactor 或 chore。
Q9:数据库表结构变更用什么类型?
A:看变更目的:
- 新增功能带来的表结构变更,随功能一起算
feat - 修复bug带来的表结构修正,算
fix - 优化查询性能的表结构调整,算
perf - 纯表结构重构,功能不变,算
refactor
建议数据库变更单独提交,方便追溯。
Q10:团队有人总是不遵守规范怎么办?
A:
- 先上工具:用husky + commitlint 强制拦截,不规范根本提交不了,从技术上解决问题,不用人工提醒
- 再讲价值:跟大家说明规范的好处,不是为了卡人,是为了提升所有人的效率
- 纳入评审:代码评审时同步检查提交信息,不规范的要求修改后再合并
- 以身作则:团队负责人、老员工带头遵守,做好榜样
Q11:规范太严格会不会影响开发效率?
A:不会。 写一个规范的提交信息只需要多花十几秒,但换来的是后续排查问题、代码评审、版本发布时节省的几小时甚至几天。 而且有交互式提交工具,几乎不用动脑子,跟着选就行,学习成本非常低。 短期看增加了一点工作量,长期看是大幅提升团队协作效率。
Q12:老项目历史提交都不规范,要不要全部改?
A:不建议改历史提交。 修改历史提交会影响所有协作者,有风险,而且收益不高。 正确的做法是:从现在开始,新的提交全部遵守规范,历史的不用管。随着时间推移,规范的提交会越来越多,历史慢慢就被覆盖了。
13. 其他
13.1 速查表
# 类型速查
feat: 新增功能 fix: 修复Bug
docs: 文档变更 style: 代码格式
refactor: 代码重构 perf: 性能优化
test: 测试相关 chore: 工程配置
ci: CI/CD流程 revert: 回滚提交
# 格式模板
type(scope): subject
body
footer13.2 Git常用命令
查看完整Git命令 →查看提交历史
# 简洁查看提交历史
git log --oneline
# 查看最近n条提交
git log -n 10 --oneline
# 按作者筛选
git log --author="张三" --oneline
# 按类型筛选(比如只看feat)
git log --grep="^feat" --oneline修改提交信息
# 修改最近一次提交的信息
git commit --amend
# 交互式变基,修改历史提交
git rebase -i HEAD~5回滚提交
# 回滚指定提交,生成新的回滚提交
git revert <提交哈希>
# 重置到指定提交,保留改动(谨慎使用)
git reset --soft <提交哈希>