最后更新:

Git 提交消息的写法 - 字数标准与最佳实践

8 分钟阅读

字数标准的约束力到什么程度

"标题行 50 字符、正文 72 字符换行"这一惯例的起源可以追溯到电子邮件的时代。Git 的开发者 Linus Torvalds 把 Linux 内核开发中通过邮件收发补丁的习惯带进了 Git。邮件客户端的标准显示宽度是 80 列,考虑到引用符号和缩进,正文取 72 字符是最合适的。

提交消息的长度之所以被反复讨论,是因为它同时要面向两类读者:在终端里快速浏览历史的人,以及几个月后追查某个变更缘由的人。前者需要一眼能读完的短标题,后者需要正文里完整的背景说明。标题行和正文的字数标准,正是为了同时照顾这两种用法而形成的分工:标题行负责检索,正文负责解释。

需要先分清一点:Git 自身并不限制提交消息的长度。标题行 50 字符、正文 72 字符都不是程序强制的上限,而是为了在终端和各类工具中都便于阅读而形成的运用参考值,超出并不会导致提交失败,只是可读性会打折。另外采用 Conventional Commits 时,前缀 (feat: 或 fix:) 本身就会占掉 5-10 字符,留给说明部分的字数预算相应缩水,落笔时需要把前缀一起算进去。

提交消息的标准格式

被广泛接受的 Git 提交消息格式由三部分组成:

标题行 (最多 50 字符)

正文 (每行 72 字符换行)

脚注 (可选)

标题行和正文之间必须有一个空行。这是 Git 工具链正确解析提交消息的前提。这一结构对应着 git log --oneline 和 GitHub 提交列表中只显示标题行的机制。

各平台在哪里给标题加省略号并没有公开的规格,而且提交列表、仓库首页、拉取请求页面的可用宽度各不相同,还会随界面改版而变化。因此以某个具体位数为目标去微调标题,投入的功夫往往得不到回报。把标题写得足够短、让开头就能读出变更要点,才是更稳妥的做法。

要素字数标准理由
标题行 (subject)50 字符以内 (英文)Git 官方手册 (git commit 的 DISCUSSION) 推荐的长度
标题行 (实用上的上限)72 字符以内80 列终端下 git log --oneline 不换行就能容纳的宽度
正文每行72 字符换行终端标准宽度 (80 列) 扣除缩进后的数值
正文整体无限制可以按需要写入详细说明

全角与半角的字数差异也需要注意。包含中日文等全角字符的提交消息,标题行以 25 字符左右为标准,就不容易在 GitHub 上被截断。

为什么是 50 字符和 72 字符

限制字符数技术原因
标题行50 字符 (实用上限 72)Git 官方手册推荐 50 字符以内;72 字符是 80 列终端下 git log --oneline 的可用宽度
正文换行72 字符git log 默认缩进 4 字符,终端标准宽度 80 字符,80 - 4 - 4 = 72

50 字符这个数值有明确的出处:Git 官方手册 (git commit 的 DISCUSSION 一节) 推荐把标题行控制在 50 字符以内。另一个常被提到的 72 字符,则来自 80 列终端下 git log --oneline 留给标题的可用宽度。两者都不是 Git 会强制检查的限制。

72 字符的正文换行规则源于终端的标准宽度 (80 列)。git log 默认在左侧添加 4 个字符的缩进,右侧也预留 4 个字符的边距,因此正文的有效宽度为 72 字符。

这里容易误解的是 git log 的默认 (medium) 格式:提交哈希值单独占一行,标题行和正文统一缩进 4 个空格,标题并不会被哈希值挤掉宽度。真正与 72 字符相关的是 git log --oneline:缩短哈希值 (7 字符) 加一个空格先消耗 8 列,在 80 列终端下留给标题的正好是 72 列。50 字符这一推荐值,就是相对于这个 72 列上限留出余地的"软限制"。

正文 72 字符换行同样有明确的依据。git format-patch 生成的补丁邮件在邮件列表里被引用时,行首会加上 > (2 字符)。两级引用 (> > ) 为 4 字符,再加上 4 字符缩进,要装进 80 列的显示宽度,上限正好是 72 字符。这个计算作为 72 字符规则的说明被广泛共享,不过 Git 的手册本身并没有规定正文的换行宽度。

Conventional Commits 规范

Conventional Commits 是一种结构化的提交消息格式,被越来越多的项目采用。在消息开头加上前缀 (类型),变更的种类就一目了然,还能与 CHANGELOG 的自动生成和语义化版本号联动:

<type>(<scope>): <description>

[optional body]

[optional footer(s)]
类型 (type)含义示例
feat新功能feat(auth): add OAuth2 login
fix修复 bugfix(api): handle null response
docs文档变更docs: update API reference
style代码格式 (不影响逻辑)style: fix indentation
refactor重构 (不改变功能)refactor: extract helper function
test测试相关test: add unit tests for parser
chore构建/工具变更chore: update dependencies
perf性能优化perf(search): add index for full-text query
ciCI/CD 配置变更ci: add GitHub Actions workflow

这一规范的设计思想在于与语义化版本 (SemVer) 的自动联动。feat 对应 MINOR 版本的更新,fix 对应 PATCH 版本的更新,包含 BREAKING CHANGE 脚注的提交则表示 MAJOR 版本的更新。有了这层对应关系,semantic-release、standard-version 等工具就能从提交历史自动确定版本号。

基本格式是 <type>(<scope>): <description>。scope 可以省略,用于标明变更所涉及的模块或组件。

Conventional Commits 的优势在于可以自动生成 CHANGELOG、自动确定语义化版本号,以及让提交历史更加结构化和可搜索。使用前缀后,只要浏览 git log --oneline 的输出就能把握变更的全貌。团队开发时,把前缀的种类和用法写成文档,运用起来会更顺畅。

为什么推荐使用祈使语气 (imperative mood)

英文提交消息推荐祈使语气,理由植根于 Git 自身的设计。Git 自动生成的消息 (Merge branch 'feature'、Revert "Add login form") 都使用祈使语气。用户写的消息与之保持一致,git log 的整体输出就会形成统一的文体。

祈使语气的消息可以读作"应用这个提交之后会发生什么"的句子。Add user authentication 意为"添加用户认证",简洁地表达了提交的效果;而 Added user authentication (过去式) 是"添加了用户认证"的报告,记录的是作业过程而不是提交的效果。

判断不清时,可以把消息填进 "If applied, this commit will ___" 的空格里,看读起来是否自然。If applied, this commit will add user authentication 很自然,而 If applied, this commit will added user authentication 在语法上就不通顺。

好的提交消息 vs 坏的提交消息

提交消息的质量直接关系到项目的可维护性。下面把实务中常见的坏例子与改进后的好例子对照列出。

❌ 坏的示例✅ 好的示例改善点
fix bugfix(auth): prevent session timeout on idle明确了修复的内容和范围
updatefeat(dashboard): add real-time chart updates说明了具体的变更内容
WIPrefactor(api): extract validation middleware描述了重构的具体操作
asdfghdocs: add deployment guide for production提供了有意义的描述
Fixed the thing that was broken in the last commit because it was not working properlyfix(auth): restore session after token refresh冗长且大幅超过 50 字符,改为简洁表述

标题行的写作规则

  1. 使用祈使语气:写"Add feature"而不是"Added feature"或"Adding feature"。这与 Git 自动生成的消息 (如 "Merge branch") 保持一致。
  2. 首字母大写:标题行的第一个字母大写 (使用 Conventional Commits 时,type 小写,description 首字母大写)。
  3. 不加句号:标题行末尾不加句号。这是节省字符的惯例。
  4. 说明"做了什么"而非"怎么做的":"Fix login error"比"Change auth.js line 42"更有价值。

正文的写作指南

中文提交消息的特殊考虑

虽然英文是 Git 提交消息的主流语言,但在中文团队中使用中文提交消息也是合理的选择。此时字符数与字节数的区别会带来实际问题:Git 内部以 UTF-8 处理字符串,一个全角字符要消耗 3 字节。而 GitHub 的标题截断并非按字节数、而是按显示宽度 (列数) 判定,全角字符占 2 列。也就是说,能装进 50 列显示宽度的中文最多是 25 字。需要注意:

在终端里查看 git log 时,多字节字符的宽度计算也会成为问题。多数终端模拟器依据 East Asian Width 属性把全角字符按 2 列宽显示,但在部分环境 (尤其是旧版 Windows 命令提示符) 中宽度计算不正确,显示就会错乱。如果 git log --oneline 的输出列对不齐,请检查终端的字符宽度设置。

团队采用中文提交消息时,"前缀用英文、说明用中文"的混合方式很实用。写成 fix(auth): 修复登录时的会话恢复 这样,既能让 git log --oneline --grep="^fix" 的按类型过滤继续生效,也让中文母语者读起来更轻松。

squash merge 与 revert 的消息设计

使用 squash merge 时,多个提交会被合并成一个,消息的设计因此与普通提交不同。GitHub 的 squash merge 默认把拉取请求的标题作为标题行、把各个提交消息以列表形式插入正文 (这一默认值可以在仓库设置中更改)。直接沿用这段自动生成的消息,正文往往会变得冗长。squash merge 时,用拉取请求的说明文作为正文,简洁归纳变更的目的和影响范围更为有效。

revert 提交的消息,惯例是直接沿用 Git 自动生成的 Revert "<original subject>" 格式。正文中除了原提交的哈希值 (This reverts commit <hash>.) 之外,务必写明 revert 的理由。缺少理由,日后追溯历史时就无法弄清"为什么要撤销"。如果一次性 revert 多个提交,像 revert: undo feature X (commits abc..def) 这样明确标出范围,历史追踪会更容易。

团队开发中的提交消息运用规则

下面给出 commitlint 与 husky 组合的配置示例。用 npm install --save-dev @commitlint/cli @commitlint/config-conventional husky 安装后,在项目根目录创建 commitlint.config.js,写入 module.exports = { extends: ['@commitlint/config-conventional'] };。接着用 npx husky init 初始化 husky,在 .husky/commit-msg 文件中写入 npx --no -- commitlint --edit $1,提交时就会自动运行消息验证。

与命名规范与长度指南一样,提交消息的规则也应配合团队的规模和文化分阶段引入才现实。先从统一前缀开始,习惯之后再引入 commitlint,这种循序渐进的做法更为有效。

AI 生成提交消息的活用与注意事项

GitHub Copilot 及各类编辑器扩展提供的提交消息自动生成功能,可以大幅减少撰写消息的工夫。它们会解析差异 (diff) 来概括变更内容,因此在"改了什么"的描述精度上往往较高。

不过自动生成也有局限。最大的弱点是无法推测"为什么需要这个变更"。从代码差异中读不出变更的动机和业务背景,因此应写进正文的"Why"部分需要由人来补全。此外自动生成的消息容易冗长,超过 50 字符标题限制的情况也不少。不要直接照用生成结果,务必由人来审查、删去多余信息并简洁归纳,这个习惯很重要。

Git 工具中的字符限制

工具/平台标题显示截断行为
git log --oneline完整显示终端宽度截断
GitHub 提交列表依页面宽度而定过长时加省略号 (位置未公开)
GitHub PR 合并消息完整显示不截断
GitLab 提交列表依页面宽度而定过长时加省略号 (位置未公开)
VS Code 源代码管理完整显示50 字符处显示警告

总结

Git 提交消息的字数控制不是形式主义,而是确保团队协作效率和项目可维护性的实践。标题行 50 字符以内、正文 72 字符换行是经过时间验证的最佳实践,这些数值源自终端 80 列的宽度和邮件引用的惯例,但都属于运用上的参考值,Git 自身并不限制消息的长度。采用 Conventional Commits 规范可以让变更种类一目了然,还能对接 CHANGELOG 的自动生成。用中文写消息时要注意全角字符的显示宽度,标题行以 25 字符左右为标准。好的消息会简洁地传达"改了什么""为什么改",坏的消息则含糊且信息量不足。写提交消息前使用字符计数器确认字数,养成良好的提交习惯。

分享这篇文章