技术写作不是语文课,不是追求文采,也不是额外的工作。它是工程基础设施的一部分。你写的每一个 Commit Message、每一条 PR 描述、每一个 Issue,都在决定:六个月后的你或者你的队友,能不能在不问人的情况下理解这段历史——发生了什么、为什么这样做、出了问题怎么追溯。
在异步协作的团队里,沟通能力直接影响工程速度。一个写得清楚的 Bug 报告可以让修复时间从两天变成两小时;一个写得好的 PR 描述可以让 Review 从反复拉锯变成一次通过;一个写得清楚的 README 决定了新人花多久能跑起第一个示例。
1. Commit Message
Commit Message 是最高密度的技术写作——几十个字,要让未来的任何人在不打开代码的情况下理解”这次提交做了什么,以及为什么”。
写什么
写 Why,不写 What。 What 在 diff 里一眼就能看到;Why 只在 Commit Message 里。
# 差:描述了做了什么,但不说为什么
fix: 修改了用户权限检查逻辑
# 好:说明了为什么要改
fix: 修复角色更新后权限缓存未失效的问题
旧逻辑在用户角色变更时不会刷新权限缓存,导致新角色的权限
在下次登录前无法生效。现在在角色更新时主动清除对应用户的
权限缓存条目。更改了什么,diff 会显示。为什么要改,未来的人只能靠 Commit Message 知道。
Conventional Commits 格式
大多数现代项目采用 Conventional Commits 规范:
<类型>[可选范围]: <简短描述>
[可选正文]
[可选脚注]常用类型:
| 类型 | 含义 |
|---|---|
feat | 新功能 |
fix | Bug 修复 |
docs | 文档变更 |
refactor | 重构(不改功能,不修 bug) |
test | 测试相关 |
chore | 构建、依赖、工具链等维护性工作 |
perf | 性能改善 |
Breaking Change 在脚注里用 BREAKING CHANGE: 标注,或在类型后面加 !:
feat!: 重新设计用户 API 响应结构
BREAKING CHANGE: users 字段改为 data,旧字段在 v3.0 移除Conventional Commits 不只是风格规范,它是工具链的基础:release-please、semantic-release、changelogithub 等工具可以读取 commit 类型自动生成 CHANGELOG 和决定版本号(feat → minor,fix → patch,BREAKING CHANGE → major)。
实践规则
- 第一行不超过 72 个字符(保证
git log --oneline不截断) - 第一行用祈使句(“修复……”,不是”修复了……“)
- 正文和第一行之间空一行
- 正文解释 Why 和 What,不是 How(How 在代码里)
- 一个 commit 做一件事——如果你的 commit message 里出现了”以及”,考虑拆分
2. PR 描述
PR 描述是 Reviewer 进入这段变更的入口。一个好的 PR 描述能把 Review 时间从几小时压缩到几十分钟,因为 Reviewer 不需要从代码里反推意图。
一个完整的 PR 描述包含四个维度:
做了什么:变更的范围和内容概述。不是 commit 的罗列,是这次变更的整体意图。
为什么这样做:动机——这个 PR 解决了什么问题、满足了什么需求?以及关键设计决策的理由,尤其是不显然的选择:“为什么用 X 而不是 Y”。
如何验证:Reviewer 和 QA 可以怎么自己验证这个变更是正确的?给出操作步骤或测试场景,比空谈”已测试”更有价值。
Breaking Change:如果有,明确说明影响范围、迁移路径、废弃时间表。
## 做了什么
实现了用户角色变更后的权限缓存失效机制。当用户角色被更新时,
相关的权限缓存条目会被立即清除,新权限在下次请求时生效。
## 为什么这样做
修复 #347:角色更新后用户权限不立即生效的问题。
旧实现依赖 TTL 过期(默认 1 小时),无法满足权限敏感场景。
## 如何验证
1. 创建一个普通用户,用该用户访问 /admin 页面(应该 403)
2. 在管理后台给该用户赋予 admin 角色
3. 不重新登录,刷新 /admin 页面(应该立即可以访问)
## Breaking Change
无如果 PR 有截图(UI 变更)或性能数据(优化),附上 before/after 对比,是最直接的佐证。
3. Issue 写作
Issue 是一个问题的完整记录,而不是你心里话的流水账。写 Issue 的目标:让读到它的人——维护者、三个月后的你、其他遇到同样问题的人——能在不问你的情况下完全理解这个问题。
标题公式:
[环境/版本] 操作 → 期望结果 → 实际结果
“Next.js 14 SSR 中使用 cookies() 在 Vercel 部署时报 ‘cookies() is not available‘“比”cookies 不工作了”有用得多。
正文结构(Bug 类 Issue):
## 环境
- OS / 平台版本
- 语言运行时版本
- 相关库版本
## 复现步骤
从一个干净环境开始,一步步写清楚。
最理想的是提供最小复现仓库。
## 期望行为
你认为应该发生什么。
## 实际行为
实际发生了什么。完整粘贴错误信息,不要截取片段。功能请求类 Issue 写法:说明你的使用场景和需求(Why),而不是直接描述你希望的实现方案(How)。项目方可能有更好的实现方式,或者已经有其他方案满足你的需求。
4. README
README 是项目的门面。新用户、潜在贡献者、评估工具的工程师,第一眼看的都是 README。一个好的 README 回答四个问题:
What:这个项目是什么?一句话或两句话,说清楚它解决什么问题、目标用户是谁。不要说”这是一个功能强大的框架”——说清楚它具体做什么。
Why:为什么选这个而不是现有的替代方案?不是所有项目都需要回答这个问题,但如果你的项目在一个竞争赛道上,说清楚差异化很重要。
Quick Start:从零到第一个可运行的示例,步骤尽量少。目标是让人在 5 分钟内看到结果——有结果才有继续读下去的动力。
Example:一个真实的、能展示核心功能的代码示例。比功能列表更有说服力。
不属于 README 的东西:所有功能的详细 API 文档(放单独的文档里)、贡献指南(放 CONTRIBUTING.md)、安全策略(放 SECURITY.md)。README 越长越难读,保持聚焦。
5. 技术文档的层级
文档不是一种,是一个体系。不同的文档服务于不同的读者和场景:
用户文档(Tutorial / How-to Guide):面向使用者。Tutorial 带着用户完成一个具体的任务,目的是建立使用信心;How-to Guide 解决特定场景的问题,假设用户已经有基础。两者的区别:Tutorial 说”现在做这个”,How-to 说”如果你想做 X,可以……”。
API 文档(Reference):完整描述每个函数、参数、返回值、副作用。面向已经知道自己在找什么的用户,是查阅手册,不是教程。大多数语言有工具自动从代码注释生成(JSDoc、rustdoc、godoc)。
ADR(Architecture Decision Record,架构决策记录):记录重要技术决策的背景、考虑过的选项、最终选择和理由。格式很简单:
# ADR-001: 选择 PostgreSQL 而不是 MongoDB
## 背景
我们需要存储用户数据和关联关系……
## 考虑过的选项
- PostgreSQL:强 ACID 事务,丰富的关系查询……
- MongoDB:灵活 schema,水平扩展方便……
## 决策
选择 PostgreSQL,理由是……
## 后果
……ADR 的价值在六个月后才能体会到——当有人问”我们当时为什么选这个”的时候,不需要找写代码的人来口头解释,文档里有完整的推理过程。
6. 沟通渠道的选择
不是所有沟通都应该发生在同一个地方。选错渠道不只是低效,有时会让信息永久消失(比如用 Slack 讨论了一个重要的技术决策,三个月后消息找不到了)。
| 场景 | 推荐渠道 | 原因 |
|---|---|---|
| Bug 报告、功能请求 | GitHub Issues | 可追踪、可搜索、有状态管理 |
| 开放性讨论、使用问题 | GitHub Discussions | 不会把 Issues 撑爆,有分类结构 |
| 技术决策、设计方案 | Issue / PR / ADR | 有记录,后来者可以读到推理过程 |
| 快速澄清、实时协调 | Discord / Slack | 实时,但消息可能消失 |
| 安全漏洞 | SECURITY.md 指定渠道 | 不能公开 |
| 跨时区团队协调 | 异步文档 + Issues | 不依赖同时在线 |
异步优先是分布式团队的基本原则。把决策记录在文档里,让人可以在自己的时区参与,而不是依赖实时会议。会议可以加速达成共识,但结果要写下来——“我们在视频里讨论过了”不算沟通,写下来才算。
公开问题公开解决:除非涉及隐私或安全,尽量在 Issues / Discussions 里沟通,而不是私信维护者。公开的讨论可以被搜索到,帮助后来遇到同样问题的人。
7. AI 辅助写作
AI 可以显著降低技术写作的门槛,尤其对非母语写作者(用英文参与全球开源社区)帮助很大。
AI 适合做的:帮你整理 Commit Message 的格式、润色 Issue 描述的措辞、生成文档的初始草稿、把你描述的场景翻译成清晰的英文。
AI 不适合替代你做的:判断一个设计决策的理由(AI 不知道你的系统约束);核实错误信息和版本号(AI 可能编造不存在的 API 或错误代码);验证操作步骤是否真的可以复现(AI 只是在猜)。
使用原则:AI 生成的内容,你发出去之前要读一遍,确认每一个技术细节是真实的。错误的技术细节比没有帮助更有害——维护者会按照你描述的步骤去尝试复现,如果步骤有误,消耗的是双方的时间。
技术写作里最终有价值的东西——准确的上下文、真实的约束、诚实的不确定性——AI 无法替你提供,只有你知道。