规范的PR是什么样

Posted by     "" on Friday, March 6, 2026

规范的 PR(Pull Request)是开源协作的核心。一个优秀的 PR 不仅能让维护者快速理解并信任你的改动,还能大大增加被合并的概率。

下面从结构规范代码规范描述规范三个维度来拆解。

一、PR 标题规范

标题是维护者第一眼看到的内容,必须简洁清晰。

格式模板

<类型>(<范围>): <简短描述>

类型说明

类型 说明 示例
feat 新功能 feat(search): 添加中文拼音搜索支持
fix 修复 bug fix(cache): 修复缓存过期导致的空指针异常
docs 文档更新 docs(readme): 更新安装步骤
refactor 重构(不改功能) refactor(logger): 统一日志格式
perf 性能优化 perf(index): 优化倒排索引构建性能
test 测试相关 test(parser): 增加边界条件测试用例
chore 构建/工具变动 chore(deps): 升级依赖版本
revert 回滚之前的提交 revert: 回滚 feat(search) 提交

示例对比

❌ 不好的标题 ✅ 好的标题
fix bug fix(consumer): 修复 rebalance 时 offset 提交失败的问题
update code feat(api): 添加批量删除评论的接口
修改了一堆东西 refactor(storage): 将文件存储抽象为接口

二、PR 描述规范

PR 描述是让维护者理解为什么做怎么做的的关键。

推荐模板

## 概述
<!-- 用一两句话说明这个 PR 做了什么 -->

## 相关 Issue
<!-- 关联的 issue 编号,如 Fixes #123 -->
Fixes #(issue编号)

## 变更内容
<!-- 列出主要变更点,可以是 bullet points -->
- [ ] 变更点 1
- [ ] 变更点 2

## 测试说明
<!-- 说明你是怎么测试的 -->
- 单元测试: ✅ 通过
- 集成测试: ✅ 通过
- 手动测试场景: xxx

## 影响范围
<!-- 说明这个改动会影响哪些模块/功能 -->
- 影响模块: consumer group
- 兼容性: 向后兼容

## 截图(如适用)
<!-- UI 类改动建议附截图 -->

完整示例

## 概述
为评论搜索添加 IK 中文分词支持,替换原有的 ngram 分词器。

## 相关 Issue
Fixes #2345

## 变更内容
- 新增 IK 分词器配置选项
- 在创建索引时支持选择 `ik_max_word``ik_smart`
- 添加分词器的单元测试
- 更新配置文档

## 测试说明
### 单元测试
```bash
go test -v ./analyzer/... -run TestIKTokenizer

全部通过 ✅

手动测试

  1. 创建索引并指定分词器为 ik_max_word
  2. 索引文档 “这个电影很好看”
  3. 搜索 “好看” → 能匹配到 ✅
  4. 搜索 “电影” → 能匹配到 ✅

影响范围

  • 影响模块: 索引创建、查询解析
  • 配置变更: 新增 index.analyzer.ik.enabled 配置项(默认 false)
  • 兼容性: 默认关闭,不影响现有用户

相关文档


## 三、代码规范

### 3.1 提交粒度

**一个 PR 只做一件事**。

| ✅ 好的粒度 | ❌ 坏的粒度 |
|------------|------------|
| 修复一个具体的 bug | 修复三个无关的 bug |
| 添加一个完整的功能 | 加功能和修 bug 混在一起 |
| 重构一个模块 | 重构十个文件 + 加新功能 + 修 typo |

**黄金法则**:如果你无法用一句话说清楚这个 PR 做了什么,那它可能太大了。

### 3.2 Commit 规范

一个 PR 可能包含多个 commit,每个 commit 也应该是原子化的。

```bash
# ✅ 好的 commit 历史
commit abc123: feat(search): 添加 IK 分词器配置
commit def456: test(search): 添加 IK 分词器单元测试
commit ghi789: docs(search): 更新分词器文档

# ❌ 坏的 commit 历史
commit xyz: update
commit abc: fix
commit 123: 改了一堆

3.3 代码风格

要求 说明
遵循项目风格 不要引入新的代码风格,参考项目现有代码
运行格式化工具 如 gofmt、prettier、black 等
通过 Linter 确保没有 Linter 警告
添加注释 复杂逻辑必须有注释解释
测试覆盖 新代码尽量有对应的测试用例

3.4 兼容性考虑

// ❌ 破坏兼容性
public void process(Comment comment) {
    // 新版本要求 comment 不能为 null
    // 旧版本调用方可能传 null
}

// ✅ 保持兼容性
public void process(Comment comment) {
    if (comment == null) {
        // 降级处理,保持旧行为
        return;
    }
    // 新逻辑
}

四、流程规范

4.1 PR 创建前的自检清单

## PR 提交前检查清单
- [ ] 代码能在本地编译通过
- [ ] 所有测试用例通过(包括新增的)
- [ ] 没有引入 Linter 警告
- [ ] 已经 rebase 了最新的 main/master 分支
- [ ] commit 信息清晰,没有 WIP、tmp 之类的提交
- [ ] PR 描述完整,说明了做什么和为什么做
- [ ] 没有混入无关文件的修改(如 IDE 配置文件)

4.2 PR 创建后的沟通规范

场景 做法
维护者提了意见 及时回复,讨论修改方案
需要修改代码 不要关掉 PR 重开,直接 push 新 commit
修改完成 回复 “已修改,请重新审核”
多轮修改 可以 squash 中间 commit,但不要 force push 到正在审核的分支

4.3 响应 Review 意见

## ✅ 正确的响应方式
维护者: "这里用 map 代替 slice 会更好"
回复: "已修改,使用 map[string]bool 替代" + 附上修改后的代码链接

## ❌ 错误的响应方式
- 直接关掉 PR 重开
- 忽略意见,等维护者再次提醒
- 回复 "我觉得这样就行"(除非你有充分理由)

五、完整示例对比

❌ 不规范的 PR

标题: fix bug

描述: 如题

Commit 历史:

a1b2c3: fix
d4e5f6: update
g7h8i9: fix again

✅ 规范的 PR

标题: fix(consumer): 修复 rebalance 时 offset 提交失败的竞态条件

描述:

## 概述
在 consumer rebalance 过程中,offset 提交可能因为分区被撤销而失败。
这个 PR 在提交前检查分区是否仍属于当前 consumer。

## 相关 Issue
Fixes #4567

## 变更内容
- 在提交 offset 前增加分区所有权检查
- 添加相关的单元测试

## 测试说明
```bash
go test -race ./consumer/... -run TestRebalance

新增测试用例 TestCommitDuringRebalance 通过

影响范围

  • 影响模块: consumer coordinator
  • 兼容性: 完全向后兼容

Commit 历史:

abc123: fix(consumer): 添加 rebalance 时的分区所有权检查
def456: test(consumer): 添加 rebalance 竞态条件测试

六、快速记忆清单

维度 核心要求
标题 <类型>(范围): 简短描述
描述 说清楚做了什么、为什么、怎么测的
粒度 一个 PR 只做一件事
Commit 原子化,信息清晰
代码 遵循风格、有测试、有注释
兼容性 不破坏现有行为
响应 及时、礼貌、有改必应

一句话总结:规范的 PR 让维护者不用问你任何问题就能理解你的改动并决定是否合并。维护者的时间是最宝贵的资源,为他们节省时间,你的 PR 就更容易被合并。