4.1 PR 标题:和 commit subject 同一套规则
PR 标题在 GitHub 上扮演两个角色:(a) 在 PR 列表里被快速扫读;(b) 默认会作为 squash merge 时的 commit message。所以它的写作规则和 commit subject 完全一致:祈使句、动词原形、Conventional Commits 风格。
# Good
feat(auth): add OAuth2 PKCE flow for mobile clients
fix(payments): retry callback on transient 5xx errors
refactor(db): extract connection pool config
# Bad
Authentication improvements # 名词,不知道改了什么
Added OAuth2 # 过去式
[WIP] new feature for auth # WIP 不该出现在 ready 的 PR
解决了一个 bug # 中文
Some changes # 等于没说
额外建议:标题前加 [WIP] / Draft: / RFC: 表示状态:
Draft: feat(api): explore GraphQL gateway
RFC: pluggable authentication backend
[WIP] performance: experiment with B-tree storage
但更现代的做法是:使用 GitHub 自带的 Draft PR(点击 "Create draft pull request"),就不用加前缀了。
4.2 PR 描述:Why / What / How / Test plan
大型项目通常都有 PR template,几乎都遵循以下四段:
# 标准 PR template
## Why
- <问题背景>
- <需求来源 / 用户痛点>
## What
- <改了什么>
- <关键决策>
- <不在范围内的事项>
## How
- <实现思路 / 架构变化>
- <迁移步骤(如有)>
## Test plan
- [ ] <手动验证步骤 1>
- [ ] <手动验证步骤 2>
- [ ] Added unit tests in `path/to/test`
- [ ] CI green
## Screenshots / Videos
<UI 类必备>
Closes #1234
Why 段落怎么写
Why 是 PR 描述里最重要但最常被中国程序员忽略的部分。它的写作公式:
- The status quo(现状):现在系统是怎么样的?
- The problem(问题):现状有什么问题?
- The trigger(触发):为什么现在要解决?
实例:
## Why
The login endpoint currently has no rate limit. We've seen
~50k failed credential-stuffing attempts per hour during peak
spikes (see incident #INC-2451). Without rate limiting, a single
malicious IP can saturate the auth service and degrade login
latency for legitimate users.
This PR introduces a sliding-window rate limiter on /login.
What 段落怎么写
What 列出 diff 的关键点,重点是分类而不是逐文件描述:
## What
- Adds `RateLimiter` interface and `RedisSlidingWindowLimiter` impl
- Wires the limiter into the `/login` handler
- Adds env vars `LOGIN_RATE_LIMIT` and `LOGIN_RATE_WINDOW`
- Updates `docs/auth.md` with the new behavior
- **Out of scope**: rate limiting on other endpoints (separate PR)
"Out of scope" 一行很重要——它告诉 reviewer 你主动选择了不做某事,避免对方提出"为什么不顺便也加上 X"。
How 段落怎么写
How 解释架构选择和关键 tradeoff:
## How
We chose a sliding window over a token bucket because it gives
smoother throttling under bursty traffic. Storage is in Redis
to allow horizontal scaling of the auth service.
Migration: none. The limiter is gated behind the feature flag
`auth.rate_limit_enabled` (default false). We'll roll it out to
1% → 10% → 100% over a week.
Test plan 段落
Test plan 是 PR 里的"合同"——你向 reviewer 承诺这些测试都通过了:
## Test plan
- [x] Unit tests in `internal/auth/limiter_test.go` (95% coverage)
- [x] Integration test against local Redis
- [x] Manual: hammer /login with `hey -n 1000 -c 50`; observed 429 after limit
- [x] Manual: confirmed feature flag off → no rate limit applied
- [x] CI green
- [ ] **Pending**: load test in staging (will run after merge)
checkbox 必须真的去勾。Reviewer 会看到没勾的 box 就追问。
4.3 Issue 引用关键词
GitHub 识别一组特殊关键词,PR 合并时会自动关闭对应 issue:
| 关键词 | 语义 | 合并后 |
|---|---|---|
Closes #123 | 关闭 | 自动 close issue |
Close #123 | 同上 | 自动 close |
Closed #123 | 同上 | 自动 close |
Fixes #123 | 修复 | 自动 close(语义偏 bug) |
Fix #123 | 同上 | 自动 close |
Resolves #123 | 解决 | 自动 close(正式语) |
Refs #123 | 引用 | 仅链接,不关闭 |
See also #123 | 参见 | 仅链接 |
Part of #123 | 部分实现 | 仅链接(用于多 PR 实现一个 epic) |
Reverts #123 | 回滚 PR | 仅链接 |
跨仓库引用:
Closes octocat/hello-world#123
Refs https://github.com/torvalds/linux/issues/4567
"Closes" 必须放在 PR 描述的 body(不能只在 commit message 里)才能触发关闭。多个 issue 必须每个都加关键词:Closes #1, #2 ❌;Closes #1, closes #2 ✓。
4.4 Issue 三大类型
类型 1:Bug Report(bug 报告)
这是最常见、也最容易写差的 issue 类型。模板:
## Description
<一句话描述 bug,避免 "doesn't work">
When uploading a file larger than 100 MB to /api/upload, the server
returns 502 instead of streaming the upload. This started after v2.4.0.
## Steps to reproduce
1. Run `./scripts/start-local.sh`
2. `curl -F file=@large.bin http://localhost:8080/api/upload`
where `large.bin` is > 100 MB
3. Observe response
## Expected behavior
Server should stream the upload and return 200 with the file metadata.
## Actual behavior
Server returns 502 Bad Gateway after ~30 seconds. Logs show:
```
upstream prematurely closed connection
```
## Environment
- App version: v2.4.1 (commit a1b2c3d)
- OS: Ubuntu 22.04 LTS
- Browser: N/A (curl)
- Reverse proxy: nginx 1.24
## Additional context
Bisected to commit 7f3a9c2 ("refactor: switch to streaming uploads").
Reverting that commit fixes the issue.
Bug Report 必备字段
| 字段 | 英文 | 典型措辞 |
|---|---|---|
| 描述 | Description / Summary | "When X, Y happens instead of Z." |
| 复现步骤 | Steps to reproduce / Repro steps | 编号列表,命令可直接复制 |
| 预期 | Expected behavior | "Should return 200 with..." |
| 实际 | Actual behavior | "Returns 502 with error..." |
| 环境 | Environment / System info | 版本、OS、浏览器等 |
| 截图 / 日志 | Screenshots / Logs | 关键线索 |
| 变通 | Workaround | "As a workaround, users can..." |
| 附加 | Additional context | git bisect 结果、相关 issue 等 |
类型 2:Feature Request(功能请求)
## Problem
When deploying to multiple environments (dev/staging/prod), I have
to maintain three nearly-identical config files. Any change must be
copy-pasted to all three, which is error-prone.
## Proposed solution
Add support for environment-specific config overlays, e.g.:
```yaml
# config.yaml (base)
db:
pool: 10
# config.production.yaml (overlay)
db:
pool: 50
```
The CLI would merge them when started with `--env=production`.
## Alternatives considered
- Templating with envsubst — works but obscures the final config
- External tool like Helm — overkill for our scale
## Additional context
Similar pattern in <link to another tool>; Kubernetes uses kustomize
for the same problem.
Feature Request 写作要点
- 先讲 Problem,再讲 Solution。 直接提方案的 issue 经常被 maintainer 反问"你到底要解决什么"。
- "Alternatives considered" 是加分项——证明你思考过,不是要 maintainer 替你思考。
- 避免 "It would be nice if..." 句型——这是被动语气,看起来是在请求别人做事。改成"This would help us..."或"I'd like to propose..."
类型 3:Question / Discussion
很多大型项目(Vue、Node.js、TypeScript)已经把"问问题"挪到 GitHub Discussions 而不是 Issues。但如果项目还允许在 Issues 里问,模板:
## Question
I'm trying to use library X with framework Y. The README mentions
Z is supported, but I can't find an example showing how.
## What I tried
- Followed the basic README setup
- Looked at the `/examples` folder — no Y example
- Searched closed issues — found #345 but it's outdated
## Code / Setup
```js
// minimal repro
import { x } from 'lib-x'
// ...
```
## Question
Is Y still supported? If yes, is there a recommended pattern?
4.5 礼貌话术:请求与拒绝
请求别人做事
| 语气 | 句型 | 场景 |
|---|---|---|
| 正式 | Could you please ... | 对 maintainer / 不熟的人 |
| 正式 | Would you mind ... | 请求小帮助 |
| 正式 | I would appreciate it if ... | 需要明显帮助 |
| 中性 | Could you ... | 同事 / 同级 |
| 中性 | Would it be possible to ... | 不确定能否做到 |
| 中性 | Any chance you could ... | 知道对方很忙时 |
| 非正式 | Mind ...? | 熟悉的同事 |
| 非正式 | Quick favor — could you ... | 小事 |
对比例子:
# 中式直译(看起来命令式)
You should review my PR.
Please reply me as soon as possible.
# 地道写法
Could you take a look at this PR when you have a chance?
A reply this week would be much appreciated, but no rush.
拒绝别人请求
拒绝是中国程序员最难写的英语场景。规则:软化 + 说明原因 + 给替代方案。
| 句型 | 用法 |
|---|---|
| I'm afraid we won't be able to ... | 正式拒绝,含遗憾 |
| Unfortunately, this isn't something we can ... | 制度性原因 |
| I don't think this is the right fit for ... | 方向不匹配 |
| I appreciate the suggestion, but ... | 感谢后转折 |
| This falls outside the scope of ... | 超出范围 |
| We've considered this before and decided to ... | 历史决策 |
| Closing as ... — feel free to reopen if ... | 关闭 issue 时 |
实例:拒绝一个 feature request
Thanks for the suggestion! I can see why this would be useful.
Unfortunately, this isn't something we plan to add to core. Keeping
the surface area small is one of our explicit goals — every option we
add becomes a maintenance burden across all platforms.
That said, this is a great use case for a plugin. We expose enough
hooks (see `docs/plugins.md`) that you should be able to implement
this externally. Happy to review if you draft something!
Closing for now, but feel free to reopen if you hit walls building
the plugin.
这种回复的效果:拒绝了请求,但保留了对方的尊严,提供了出路,也展示了团队的设计哲学。
道歉 / 推迟回复
# 推迟回复
Sorry for the delay — we're heads-down on the v3 release this week.
I'll get back to you by Friday.
# 因不熟悉而推迟
This is a great question but it's outside my area. Let me ping
@expert-name who knows this part better.
# 重要 issue 暂时无人手
Apologies for the slow response. We're aware of this and tracking
it in #4321; we just don't have bandwidth this quarter.
4.6 Labels / Milestones / Projects 的英文规范
常见 Label 词表
# 类型
bug, enhancement, feature, documentation, question,
duplicate, invalid, wontfix, help wanted, good first issue
# 优先级
priority: critical, priority: high, priority: medium, priority: low
P0, P1, P2, P3
# 状态
needs-triage, needs-info, needs-review, in-progress,
blocked, ready-for-review, ready-to-merge
# 模块(项目自定义)
area: auth, area: api, area: ui, area: docs
# 影响范围
breaking-change, security, performance, accessibility (a11y)
# 难度
easy, medium, hard, complex
# 版本
v2.x, v3.x, backport-v2
# 其他常见
stale, on-hold, discussion, RFC
Milestone 命名
v2.4.0
v2.4.0 - April 2024
2024 Q2
Sprint 23
Backlog
Icebox
Backlog(待办)和 Icebox(冷冻)是约定俗成:前者是"还没排期",后者是"无限期搁置"。
4.7 PR 全流程英语模板
开 PR:标题 + 描述
Title: feat(auth): add OAuth2 PKCE flow
(use template above)
请求 review
@reviewer1 @reviewer2 ready for review when you have a moment.
@reviewer1 could you take a primary pass; @reviewer2 a secondary?
This is small and self-contained — should be quick.
对 review 回复
# 接受意见
Good catch, fixed in <commit-sha>.
Done. Renamed to `userProfile` everywhere.
# 解释为何不改
I considered that, but went with the current approach because <reason>.
Happy to discuss further if you feel strongly.
# 标记为后续 PR
Agreed this needs work, but it's pre-existing and out of scope here.
Filed #4998 to track.
# 推迟决定
Let me sleep on this and get back to you tomorrow.
合并前的 nudge
Friendly ping — would love to get this in before the v2.5 freeze on Friday.
Bump — anything blocking this from merging?
Last call for comments before I merge.
合并后通知
Merged. Will be in v2.5 (release next Monday).
Thanks @reviewer1 @reviewer2 for the thorough review!
4.8 本章小结
- PR 标题 = commit subject 同规则。
- PR 描述四段:Why / What / How / Test plan。Why 最重要也最常被忽略。
- 关联关键词:
Closes/Fixes/Resolves自动关闭,Refs/See also/Part of仅引用。 - Issue 三类:Bug Report(八字段必备)/ Feature Request(先 Problem 后 Solution)/ Question。
- 礼貌请求:
Could you / Would you mind / Any chance;拒绝:I'm afraid / Unfortunately / Out of scope。 - Labels 用英文词表,Milestone 用
vMAJOR.MINOR.PATCH或YYYY QN。
下一章我们专门研究 Code Review 这个最考验英语功底的协作场景。