十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何通过阅读已合并PR提升代码设计能力?

如何通过阅读已合并PR提升代码设计能力? 打开 GitHub很多同学的第一反应是“这个仓库 star 多、代码能不能看懂”却很少有人会专门去翻一个仓库的 Pull requests 列表尤其是已经合并merged的 PR。原因很真实PR 动态更新快、信息密度高看起来不像源码那样有稳定的阅读入口。但如果你希望提高代码设计能力、理解一个成熟项目为什么会变成今天的样子已合并的 PR 比源码本身更值得阅读。这篇文章会围绕一个核心问题展开哪些仓库repos的已合并 PR 值得读如何快速找到它们读的时候又应该重点看什么我会从 GitHub 搜索语法、GitHub CLI、API 调用到具体阅读方法给出可以直接照做的流程。无论你是刚入门开源的同学还是已经写了几年业务代码、想提升代码设计能力的开发者这套方法都适用。1. 背景与核心概念1.1 什么是已合并的 PRPull Request简称 PR是 GitHub 上的一种协作机制。开发者从主干分支切出一个新分支完成一段功能或修复后向原仓库发起合并请求维护者和其他贡献者可以在 PR 里查看代码差异、提出评论、反复修改最终由有权限的人点击“Merge pull request”完成合并。PR 的状态通常有三种Open还在讨论和修改中。Closed不是被合并而是被关闭比如功能取消、分支废弃。Merged已经被合入目标分支是仓库正式演进的一部分。我们说的“已合并 PR”就是第三类。它和普通的 commit 不同一个 PR 可能包含多个 commit也会包含完整的描述、评审意见、自动化检查结果、讨论过程甚至还有对应的 issue 链接。所以它是一个比 commit 更完整的“改动单元”。1.2 从源码阅读到 PR 阅读的转变很多同学阅读开源项目时只盯住主干分支的源码文件比如从src/core/index.ts开始往下看。这种方式不是不行但会遇到几个问题不知道某个函数为什么这么写。看不到设计取舍和备选方案。很难还原代码演进过程。而一个 merged PR 恰好补上了这些信息。它把一次修改的“为什么做、怎么做、改了什么、如何测试”放在同一个页面上。阅读源码是看“结果”阅读 PR 是看“过程”。把两者结合起来才能更完整地理解一个项目。1.3 已合并 PR 的三个核心价值第一学习代码规范与风格。大型项目通常有严格的 ESLint、Prettier、Checkstyle、Go fmt 等规范PR 里的每一个新改动都会经过这些检查。反复看高质量 PR能慢慢培养出自己的代码审美。第二理解架构演进的取舍。比如 Vue Core 某次重构从某个函数改成了另一个设计为什么要换PR 描述里往往会写动机review 里也经常出现“为什么不直接这样写”的讨论。第三学习测试思路。很多高质量的 PR 会同步补充最小化复现用例、单元测试、快照测试或端到端测试。测试代码往往比业务代码更能体现对边界条件的思考。所以阅读 merged PR 本质上是在围观一次真实的代码评审过程。这种学习方式比单纯刷文档有意思得多也更贴近大厂内部 Code Review 的日常。2. 哪些仓库和 PR 更值得读2.1 优秀 merged PR 的特征不是所有 merged PR 都值得逐字阅读。有些 PR 可能只是改了一个错别字或者更新了文档链接。我们优先找具备下面这些特征的 PR特征说明改动范围适中能在一个 PR 里看完通常 100 到 500 行功能或修复目标明确对应具体的 issue 或需求有高质量描述说明背景、方案、风险和测试方法Review 讨论丰富维护者提出过有效修改意见包含测试用例新增或修改测试Commit 划分清晰一个 PR 拆成多个逻辑连贯的 commit来自成熟仓库有完善贡献规范和自动化检查如果你看到一个 PR 改了几十个文件、超过 3000 行有时候也值得读但更适合有经验后再挑战。新手一开始还是从“范围适中、信息完整”的 PR 入手。2.2 选择仓库的策略关于“Which repos have merged PRs worth reading”可以先从你自己熟悉的项目开始。熟悉一个项目的业务概念和模块结构后看它的 PR 会轻松很多。也可以从下面几类仓库里选你日常使用的开源框架或工具比如 Vue、React、Vite、Express 等。以代码质量著称的项目比如 TypeScript、Rust 官方工具链、GitLab CE。你所在技术栈的知名企业项目比如 Spring 系列、Kubernetes、Go 语言相关项目。通过 GitHub Trending、GitHub 官方博客、开源年会分享了解到的新项目。不建议一开始就挑战特别庞大、提交极其频繁的大型仓库而是选择“中等活跃”的项目。这类项目既有真实的讨论又不会因为 PR 数量太多让人无从下手。2.3 如何判断一个 PR 是否值得读在打开 PR 之前可以通过列表页的标题和标签先做一轮过滤标题中出现fix,feat,refactor,perf,chore等关键词。有good first issue、help wanted、reviewed等标签。打开后看到绿色Merged状态且描述不是一句话带过。如果一个 PR 的描述里有“Issue: #1234”“Motivation”“Solution”“Test plan”这样的结构化内容大概率是作者认真写过的阅读价值往往更高。3. 用 GitHub 网页搜索定位值得读的 merged PR3.1 高级搜索语法入门GitHub 自带的高级搜索足以完成大部分筛选工作。我们可以直接在 GitHub 搜索框里输入条件也可以打开https://github.com/search?q...typepullrequests进入专有的 PR 搜索页。最简单的语法是repo:vuejs/core is:pr is:merged这条语句表示在vuejs/core仓库中只搜索类型为 Pull Request且已经被合并的记录。如果你希望限制更新时间可以加上repo:reactjs/react.js is:pr is:merged merged:2024-01-01..2024-12-31GitHub 高级搜索支持的常用条件还包括语法含义repo:owner/name限定仓库is:pr只搜索 Pull Requestis:merged只看已合并的 PRlabel:bug按标签过滤reviewed-by:user指定评论人author:user指定作者commenter:user指定评论参与者head:branch-name按来源分支过滤base:main按目标分支过滤merged:2024-01-01按合并日期过滤组合使用效果更好。比如我想找 React 仓库中被某个知名维护者评审过的小型重构repo:facebook/react is:pr is:merged review:required3.2 保存搜索与订阅搜索条件确定后在搜索页面右上角点击“Save search”可以保存。下次通过左侧菜单快速打开还能看到动态变化。另外在仓库首页的 “Pull requests” 页签里可以结合搜索框再次过滤并把 URL 收藏到浏览器书签中。如果你想持续关注某个仓库的合并情况可以在仓库页右上角点击 Watch然后进入子菜单选择 “Releases only” 或 “Custom” 折叠中的 “Pull requests”。这样新 PR 动态就会出现在 GitHub 通知中心更新频率适中不会太打扰。3.3 搜索词示例下面给你几个可以直接使用的搜索示例复制到 GitHub 搜索框即可repo:vuejs/core is:pr is:mergedrepo:facebook/react is:pr is:merged label:Component: Developer Toolsorg:vitejs is:pr is:merged merged:2024-01-01is:pr is:merged author:yyx990803 archived:false最后一条中的archived:false用来排除已归档仓库。虽然是个人作者维度但也能筛出很多有代表性的 PR。4. 用命令行快速拉取 merged PR网页适合一次两次查看但如果你想把一个仓库的 merged PR 批量拉下来或者写脚本做统计分析命令行工具更高效。4.1 安装 gh CLI 与认证GitHub 官方命令行工具是gh支持 Windows、macOS、Linux。安装完成后需要进行认证gh auth login按提示选择 GitHub.com然后选择 HTTPS 和浏览器授权即可。认证成功后可以用下面命令测一下gh auth status如果看到类似Logged in to github.com as yourname的输出说明认证成功。没有安装 gh 的同学可以暂时用 curl 加 token 访问 GitHub API但gh在体验上会舒服很多。4.2 获取某个仓库最近合并的 PRgh pr list是查看 PR 列表最常用的命令指定--state merged就可以只看已合并的gh pr list --repo vuejs/core --state merged --limit 10这条命令会输出最近合并的 10 个 PR 的编号、标题和分支信息。如果你希望输出更清晰的字段可以加--jsongh pr list --repo vuejs/core --state merged --limit 10 \ --json number,title,mergedAt,url,author这个命令会输出 JSON 数组方便后续用 jq 处理。执行效果大致如下[ { number: 12345, title: fix(runtime-core): handle patchFlag in updateProps, mergedAt: 2024-06-15T08:30:00Z, url: https://github.com/vuejs/core/pull/12345, author: { login: someone } } ]注意gh pr list默认显示当前分支所在仓库。指定--repo可以避免切目录。4.3 查看单个 PR 的详情与文件变更拿到 PR 编号后使用gh pr view查看详情gh pr view 12345 --repo vuejs/core这里默认显示 PR 描述和状态。如果想看文件变更可以加--comments查看评论配合--json输出更多结构化信息gh pr view 12345 --repo vuejs/core --json title,description,files,reviews,comments这个命令在分析 PR 质量时非常好用因为files字段会包含每个文件的additions、deletions和路径reviews会包含评审状态与关键评论。在终端里快速查看某个文件的 diffgh pr diff 12345 --repo vuejs/core pr-12345.diff然后打开pr-12345.diff或直接使用 IDE 的分屏查看功能。保存到本地后也方便做笔记和后续搜索。4.4 使用 GitHub API 批量过滤如果想绕过 gh 命令直接用 GitHub REST API 也可以。仓库的 Pull Request 列表接口如下GET /repos/{owner}/{repo}/pulls?stateclosedper_page100注意这里必须用stateclosed因为 /pulls 接口没有merged状态。关闭的 PR 包括两种已合并和未合并被关闭。要判断是否真正合并需要看每个 PR 的merged_at字段非空表示已合并。使用 curl 加 jq 可以一次性清洗出合并 PRcurl -s -H Accept: application/vnd.githubjson \ https://api.github.com/repos/vuejs/core/pulls?stateclosedper_page50page1 \ | jq [.[] | select(.merged_at ! null)] | .[] | {number, title, merged_at, user: .user.login}执行后会输出类似{ number: 12345, title: fix(runtime-core): handle patchFlag in updateProps, merged_at: 2024-06-15T08:30:00Z, user: { login: someone } }需要提醒的是GitHub API 未认证状态每小时有 60 次请求限制。如果只是教学作用这个量基本够用如果要写脚本批量拉取建议设置环境变量export GH_TOKEN你的token然后在 curl 中加入请求头curl -s -H Authorization: Bearer $GH_TOKEN \ -H Accept: application/vnd.githubjson \ https://api.github.com/repos/vuejs/core/pulls?stateclosedper_page100注意不要把 token 硬编码到代码里更不要提交到公开仓库。生产环境使用 GitHub Actions 时应该优先使用secrets.GITHUB_TOKEN或secrets.PAT。5. 一次完整的 merged PR 阅读流程找到 PR 只是第一步真正有效的是阅读方法。下面推荐一套具体流程按顺序执行能帮你减少遗漏也能提高吸收率。5.1 阅读顺序建议第一步先看标题和描述。标题已经概括了这次改动的大方向比如fix(compiler): improve error message for unknown directive。描述里更可能包含背景、Issue 链接、方案对比、测试计划。第二步看提交记录。一个 PR 里通常有多个 commit先看 commit message 的演变能理解作者的思考过程。比如先加测试、再实现功能、再重构代码就是一个很好的开发节奏。第三步看文件变更总览。了解src/core/index.ts改了多少行、新增了哪些测试文件。优先关注核心源码测试文件放到第二步一起看。第四步逐文件阅读 diff。不要只看新增行还要看删除和修改的位置。很多重构的价值就在“删掉了哪些复杂度”。第五步看 review 评论。维护者的评论往往是整个 PR 中最有价值的部分因为它在指出“哪里不够好、为什么不够好、可以怎么改”。第六步看合并后的结果。如果 PR 包含了 API 变更可以再看看文档或 changelog确认实际使用方式。5.2 关注 review 讨论Review 是 PR 和普通 commit 最大的不同。一个高质量 PR 的评论区通常包含这些类型的对话“这里的命名是否更贴近现有语义”“为什么不用已有的工具函数”“这个边界条件需要补充测试。”“性能上有没有更优做法”这些内容就是活生生的 Code Review 教程。我们可以多问自己一个问题如果我是 reviewer我会不会也提出同样的意见久而久之自己的审查能力也会提升。建议在阅读时打开两个窗口一个窗口显示 diff另一个窗口显示 review 评论。这样可以避免来回滚动阅读体验更好。5.3 动手复现和延伸阅读本身是被动行为配合动手才会更牢固。你可以做下面三件事把 PR 的分支拉下来本地运行。尝试复制 PR 的变更从零实现一个小版本。在 PR 基础上补充新的测试用例给自己设定一个“如果我来改我会怎么做”的任务。如果 PR 对应一个 issue也值得打开 issue 看看用户报障的问题和讨论。这样你学到的不仅是“代码怎么改”还包括问题从报告到解决的完整链路。6. 常见问题与排查思路在筛选和分析 merged PR 时最容易遇到下面这些问题。这里列出高频现象和解决思路方便你保存。问题现象常见原因解决思路GitHub 高级搜索没有结果搜索语法输入错误或仓库本身不存在检查repo:大小写确认仓库地址是否正确搜出来的 PR 没有合并搜索时漏掉is:merged补上is:merged重新执行搜索gh命令提示 command not foundgh CLI 未安装或未加入 PATH按官方文档安装最新版重启终端gh pr list --state merged返回空仓库确实没有合并 PR或 gh 未认证执行gh auth login换一个活跃仓库测试GitHub API 请求 403未认证或达到限流等待一小时恢复或使用带 token 的请求API 返回的 PR 列表包含未合并项拉取的是stateclosed不是merged用merged_at ! null进行过滤打开 PR 后文件 diff 太大选择了跨分支合并或规模过大的 PR先按文件拆分阅读或者换一个小型 PRreview 评论很多但看不懂对项目背景不熟悉先阅读相关模块源码再回到 PR 评论这几个问题最常见的根因是“搜索状态”和“接口状态”不一致。尤其是 GitHub API 的 /pulls 接口很多人会问为什么statemerged不生效因为 REST API 本身没有这个枚举值必须用stateclosed再根据merged_at判断。避免这个问题的方法是优先使用 GitHub 高级搜索的is:merged或者使用 gh CLI 的--state merged。两者在底层都帮你做了额外过滤表达更直观。7. 将阅读能力转化为工程能力阅读别人的 merged PR 最终会沉淀为自己的工程能力。这一节我们聊聊如何把“看 PR”和“写 PR”打通。7.1 写 PR 时借鉴高质量 PR 结构一个值得被阅读的 PR往往有一个清晰的模板。常见的结构是相关 Issue。改动背景。实现方案。测试计划。影响范围与风险。你完全可以在自己的仓库里建立这样一个 PR 模板提交到.github/pull_request_template.md文件。这样团队每次提 PR 都会自动套用模板时间久了整个仓库的 PR 质量都会提升。一个简单的模板示例## Description 请描述这次改动要解决的问题。 ## Related Issue Fixes #123 ## Type of change - [ ] Bug fix - [ ] New feature - [ ] Breaking change ## How Has This Been Tested? 请描述测试环境和测试步骤。 ## Checklist - [ ] 代码格式检查通过 - [ ] 本地测试通过 - [ ] 文档已同步更新7.2 让 Code Review 更有针对性读高水平 PR 的时候可以顺手记录 reviewer 常用的提问方式整理成自己的审查清单是否缺少异常处理是否考虑到边界输入公共 API 是否有兼容性风险是否应该添加日志是否有更简单的实现方式当你在自己的 Code Review 中反复使用这些问题时审查效率会明显提高。别人也会慢慢觉得你的 review 有深度。7.3 建立自己的 PR 收藏库GitHub 本身支持给 PR 点赞和评论但更好的做法是建一个笔记仓库比如awesome-merged-prs用于整理你读过的优质 PR。可以按照这样分类按语言Go、TypeScript、Rust、Java、Python。按关注点错误处理、并发编程、缓存设计、API 设计、重构手法。按复杂度入门、进阶、挑战。每条笔记至少写清楚三个点这个 PR 解决了什么问题有哪些值得学习的点如果让我重新实现我会怎么改进。这样你积累的不只是收藏链接而是一套自己的代码设计知识库。8. 总结与学习路线这篇文章主要回答了 “Which repos have merged PRs worth reading” 这个问题。我们了解了已合并 PR 与普通 commit 的区别知道了什么样的 PR 更值得读也掌握了通过搜索语法、gh CLI 和 GitHub API 批量定位 merged PR 的方法。更重要的是我们整理了一套完整的阅读流程先看描述再看提交记录然后逐文件看 diff最后结合 review 评论吸收经验。如果你的基础比较薄弱建议先从 Vue、React、Vite 这类文档完善、社区活跃的项目开始每周只精读一个 PR配合本地运行和笔记。等技术积累足够后再挑战大型基础设施项目比如 Kubernetes、Rust 工具链等。阅读时不要贪多重要的是把每个 PR 里的设计理由、测试思路和审查意见真正消化掉。从现在开始挑一个你常用的开源项目打开 Pull requests 页签筛选 merged然后按今天说的流程动手读一个 PR 吧。你可能会发现代码世界里最有学习价值的内容并不总是藏在最终版本里。
返回列表