11.3 分支、PR 与团队工作流
本节目标:理解分支的价值,掌握 Pull Request 工作流,建立多人协作的日常节奏。
"复制一份再改"的本能
小明想给"个人豆瓣"加一个"猜你喜欢"推荐功能。但他有点犹豫——评分系统好不容易跑稳了,万一改推荐功能的时候不小心动了评分的代码,又要花时间修。
他的第一反应是:把整个项目文件夹复制一份,在副本里折腾。改好了就用副本替换原来的,改坏了就删掉副本。
你一定也有过这种本能——想试个新方案但怕搞坏现有的,于是复制一份再改。这个思路是对的,只是方式太原始。Git 有一个更优雅的机制来做同样的事:分支(Branch)。
分支:Git 版的"复制文件夹"
分支的本质就是"复制一份再改",但比复制文件夹高明得多。它不会真的复制所有文件——Git 只记录差异,创建一个分支几乎不占额外空间。你可以随时在"原版"和"副本"之间切换,改好了可以精确地合并回去,而不是整个文件夹替换。
复制文件夹的问题在于:你在副本里改了 10 个文件,原版里也改了 3 个文件(修了个紧急 bug),现在你想把副本的修改合并回原版——你得手动对比 13 个文件,确保不遗漏、不覆盖。Git 的分支帮你自动完成这件事。
你的项目默认有一个主分支,通常叫 main(有些旧仓库叫 master)。它代表"当前稳定可用的版本"。当你要开发新功能时,从 main 创建一个新分支,比如 feature/recommend,在这个分支上随便折腾。改坏了?切回 main,一切如初。改好了?合并到 main,功能上线。
main 分支就像你的"正式版",功能分支就像"草稿本"——你在草稿本上怎么涂改都不影响正式版,直到你确认满意了才把内容誊写过去。
main ─────────────────────────────────── (稳定版,不受影响)
│
└── feature/recommend ──→ 在这里开发推荐功能
改坏了?切回 main,一切如初
改好了?合并到 main,功能上线小明告诉 Claude Code "创建一个分支来开发推荐功能",Claude Code 会创建 feature/recommend 分支并切换过去。从这一刻起,小明的所有修改都在这个分支上,main 分支纹丝不动。分支名通常用 feature/xxx 表示新功能,fix/xxx 表示修 bug,refactor/xxx 表示重构——这不是强制的,但能让你和协作者一眼看出这个分支在做什么。
完整的分支工作流
让我们跟着小明走一遍完整流程。这个流程是 GitHub 上最常见的协作方式,叫做 GitHub Flow。就像做菜有各种流派,但家常菜只需要一种最简单的套路就够了——GitHub Flow 就是这个最简单的套路,你接下来跟着小明走的流程就是它的全部。
小明从 main 创建了 feature/recommend 分支,开始开发推荐算法。他和 Claude Code 一起写了推荐逻辑、添加了新的 API 接口、调整了前端页面。每完成一个小步骤就提交一次——"添加推荐算法的数据模型""实现基于评分的推荐逻辑""前端展示推荐结果"。
与此同时,朋友在另一个分支 feature/user-profile 上开发用户个人主页。两个人各自在自己的分支上工作,互不干扰。小明的推荐功能改坏了不影响朋友的个人主页,朋友的个人主页出了 bug 也不影响小明的推荐功能。这就是分支的核心价值——隔离。
开发到一个阶段,小明把分支推送到 GitHub。这样做有两个好处:代码有了云端备份,朋友也能看到他的进展。即使小明的电脑出了问题,分支上的代码也不会丢。
小明觉得推荐功能差不多了,但不想直接合并到 main——他想让朋友先看看代码有没有问题。于是他在 GitHub 上创建了一个 Pull Request(PR)。
Pull Request:帮我看看再合并
为什么不直接把分支合并到 main?
想想你写过的文档——如果别人不看就直接改了你的正文,你什么感觉?PR 就是"我改好了,你帮我看看再合并"。这个"看看"的过程叫 Code Review(代码审查),是团队协作中防止事故的关键环节。
你可能觉得"我们就两个人,还需要这么正式吗?"——需要的。不是因为流程本身有多重要,而是因为另一双眼睛真的能发现你自己看不到的问题。你写了三天的代码,脑子里全是实现细节,很容易对自己的代码产生"盲区"——你觉得逻辑没问题,但朋友一看就发现你漏了一个边界情况。
PR 的价值不只是"多一双眼睛"。朋友可能发现你遗漏的边界情况或潜在 bug——比如推荐算法没有处理用户没有评分记录的情况。通过 Review 别人的代码,朋友也了解了推荐功能的实现,这是知识共享——如果小明哪天不在,朋友也能维护推荐功能,因为他在 Review 的时候已经读过这些代码了。
所有关于这段代码的讨论都留在 PR 页面上,以后可以回溯"当时为什么这么写"。三个月后你看到一段奇怪的代码,不知道为什么要这么写,翻一下当时的 PR 讨论就能找到答案。
对于个人项目,PR 也有价值——它让你在合并前有一个"暂停、回顾"的机会。你可能在分支上连续开发了好几天,PR 的 diff 视图能帮你从全局视角审视这些修改,发现自己在细节中遗漏的问题。在发起 PR 之前,你还可以让 Claude Code 先做一轮 Self-Review——检查逻辑错误、安全隐患、性能问题。这样提交给朋友审查的代码质量更高,朋友也更愿意帮你 Review。
朋友打开 PR 页面,看到了小明改了哪些文件、每个文件具体改了哪几行。他可以在某一行代码下面留言:"这里的推荐算法没有处理用户没有评分记录的情况。"小明看到评论,修改代码,再次提交推送。PR 会自动更新,朋友可以看到新的修改。这个来回的过程可能会持续几轮——朋友提出问题,小明修改,朋友再看,直到双方都满意。这不是在浪费时间,而是在提高代码质量。很多 bug 就是在这个过程中被发现的,而不是上线之后被用户发现。
朋友确认没问题后,点击 Merge pull request。推荐功能的代码被合并到 main 分支,功能正式上线。合并后,GitHub 会提示你是否要删除这个分支。点击 Delete branch 就行——分支的使命已经完成,它的所有代码变更已经合并到了 main 里。别舍不得删,分支是廉价的,用完就扔。PR 页面上保留了所有代码变更和讨论记录,不会因为删除分支而丢失。以后你想回顾"推荐功能当时是怎么实现的",翻这个 PR 就行。

完整流程图:
main ──────────────────────────────────────── main (包含推荐功能)
│ ↑
└── feature/recommend ──→ 开发 ──→ PR ──→ Review ──→ MergeGitHub PR 页面导览
第一次创建 PR,你需要知道页面上有什么。


创建 PR 时,你需要填写标题(简要描述这个 PR 做了什么)和描述(详细说明改了什么、为什么改),然后选择要合并到哪个分支(通常是 main)。标题写清楚就行,比如"添加基于评分的推荐功能"。描述可以写得详细一些——改了哪些模块、为什么选择这个方案、有没有已知的限制。好的 PR 描述能让 Reviewer 更快地理解你的意图,Review 效率也更高。你也可以让 Claude Code 帮你创建 PR——告诉它"在 GitHub 上创建一个 PR,把 feature/recommend 合并到 main",它会通过 GitHub CLI 完成创建,包括填写标题和描述。
PR 详情页有几个标签:Conversation 是 PR 的描述和所有讨论,Commits 是这个 PR 包含的所有提交,Files changed 是所有修改的文件对比——这是 Review 的主要工作区,你能看到每个文件的每一行变化。绿色背景的行是新增的,红色背景的行是删除的,没有颜色的行是上下文(帮你理解修改发生在代码的什么位置)。Review 通过后,页面底部会出现绿色的 Merge 按钮,点击即可合并。
如果你配置了 CI/CD(第十二章会讲),PR 页面还会显示自动化检查的结果——测试是否通过、构建是否成功。检查不通过时,Merge 按钮会变灰,防止有问题的代码被合并——就像你提交表单时必填项没填,提交按钮是灰色的、点不了。这是一道自动化的安全网,不需要人工盯着。即使你现在还没配置 CI/CD,知道 PR 页面有这个能力就行——等你的项目需要更严格的质量保障时,这个功能会非常有用。
个人项目也需要分支吗
你可能会想:我一个人开发,没有朋友 Review,还需要分支和 PR 吗?
答案是看情况。如果你只是在做一个小项目,直接在 main 上开发、提交、推送,完全没问题。很多个人项目从头到尾都在 main 上开发,也运行得很好。
但当你的项目开始变复杂——比如你想同时尝试两个不同的方案,或者你想在不影响线上版本的情况下做一次大重构——分支就变得有用了。
举个具体的场景:你的项目已经部署上线了(第十二章会讲部署),用户正在使用。你想加一个新功能,但这个功能需要改好几天。如果你直接在 main 上改,改到一半的代码可能会被部署上线——半成品的功能展示给用户,体验很差。但如果你在分支上开发,main 始终保持稳定可部署的状态,新功能开发完、测试通过后再合并到 main,用户看到的永远是完整的功能。
一个折中的做法:日常小修改直接在 main 上提交,大功能或实验性改动开分支。不需要一开始就严格执行完整的 PR 流程,等你和朋友开始协作时再引入。
Git 的工作流是渐进式的——先养成频繁提交和及时推送的习惯,等这两个习惯稳定了,再引入分支和 PR。不要试图一步到位,那样只会让你觉得 Git 很麻烦。
跨平台协作:Windows 遇上 Mac
小明用 Windows,朋友用 Mac。两个人协作时,踩到了几个经典的坑。
如果你用过 Windows 和 Mac 互传文件,一定遇到过乱码、文件名显示不对的问题。Git 协作中的跨平台问题本质上是同一类事——不同操作系统有不同的"方言",需要统一。
换行符差异是最常见的坑。Windows 用 CRLF(两个字符)表示换行,Mac/Linux 用 LF(一个字符)。这两个字符在屏幕上看起来完全一样——都是换行——但在文件的二进制层面是不同的。
如果不统一,Git 会认为整个文件都被修改了——明明只改了一行代码,diff 却显示每一行都有变化,因为每一行的换行符都从 LF 变成了 CRLF(或反过来)。这叫"假 diff",会让 Code Review 变得很痛苦,因为你根本看不出真正改了什么。
解决方案是告诉 Claude Code "配置 Git 统一使用 LF 换行符",它会在项目根目录创建一个 .gitattributes 文件,写入 * text=auto eol=lf,让 Git 在提交时自动把所有文本文件的换行符转换为 LF。配置一次,整个团队都受益,以后不管谁在什么系统上开发,提交到仓库的换行符都是统一的。
文件名大小写是另一个隐蔽的坑。Windows 不区分文件名大小写——Button.tsx 和 button.tsx 在 Windows 看来是同一个文件,但在 Mac/Linux 上是两个不同的文件。
小明写了 import Button from './button',文件名叫 Button.tsx,在他的 Windows 上能跑,朋友的 Mac 上报错"找不到文件"。这种 bug 特别难排查,因为小明在自己电脑上怎么测都没问题,他会觉得"我这里明明能跑啊"。
更麻烦的是,Git 在 Windows 上默认也不跟踪大小写变更——你把 Button.tsx 重命名为 button.tsx,Git 可能根本不会检测到这个变化。解决方案是文件名统一用小写或统一用 PascalCase,团队约定好就行。
路径分隔符相对简单:Windows 用反斜杠 \,Mac/Linux 用正斜杠 /。在代码中永远使用正斜杠就行了。import { Button } from './components/Button' 在所有平台都能跑,import { Button } from '.\\components\\Button' 只在 Windows 上能跑。好消息是,大部分现代框架和打包工具已经帮你处理了路径分隔符的问题,你在代码里写正斜杠就行,不需要额外操心。
这些坑不需要你一个个记住。重要的是意识到它们的存在——当你和不同系统的朋友协作时遇到"明明代码一样但跑不起来"的情况,第一反应应该是"可能是跨平台兼容性问题",然后告诉 Claude Code 帮你排查。Claude Code 对这类问题很熟悉,通常能快速定位是换行符、大小写还是路径的问题。在项目初期就配好 .gitattributes 和文件命名规范,能省去后面很多麻烦。
日常开发节奏
当你和朋友的协作进入正轨,日常开发会形成一个固定的节奏。每天开始工作时先拉取最新代码,确保你的本地是最新的。然后创建功能分支,隔离你的工作。在分支上开发,小步快跑,频繁 commit。开发到一个阶段就推送到 GitHub,既是备份也是让朋友看到进展。功能完成后创建 PR,请求朋友审查。Review 通过后合并到主分支,最后删除功能分支保持整洁。
开始工作
↓
拉取最新代码(pull)—— 确保你的本地是最新的
↓
创建功能分支 —— 隔离你的工作
↓
开发 + 提交 —— 小步快跑,频繁 commit
↓
推送到 GitHub(push)—— 备份 + 让别人看到
↓
创建 PR —— 请求审查
↓
Review + 合并 —— 代码进入主分支
↓
删除功能分支 —— 保持整洁这个节奏不是死规矩。个人项目可以简化——不一定每次都开分支、创建 PR。但当你和别人协作时,这套流程能帮你避免大部分"代码打架"的问题。刚开始可能觉得步骤有点多,但用几次就会变成习惯。就像开车——刚学的时候觉得要同时注意方向盘、油门、刹车、后视镜,手忙脚乱。开熟了之后这些动作都是自动的,你甚至不会意识到自己在做这些事。Git 工作流也是一样,用熟了之后"pull → 分支 → 开发 → PR → 合并"就是你的肌肉记忆。
速查表
| 你想做什么 | 告诉 Claude Code |
|---|---|
| 开始新功能 | "从 main 创建一个分支来开发 xxx 功能" |
| 保存进度 | "提交当前的修改" |
| 同步到云端 | "推送到 GitHub" |
| 获取最新代码 | "拉取 main 分支的最新代码" |
| 创建 PR | "在 GitHub 上创建 Pull Request" |
| 解决冲突 | "帮我解决 Git 冲突" |
| 撤销修改 | "撤销对 xxx 文件的修改" |
| 回退版本 | "回到上一个能跑的版本" |
| 删除分支 | "删除 feature/xxx 分支" |
本节核心要点
分支让你安全地实验新功能,PR 让你在合并前获得审查,跨平台配置让不同系统的协作者能顺畅合作。这套工作流的核心不是记住命令,而是建立一个习惯:改之前开分支,合之前做 Review。
下一章:代码在 GitHub 上了,怎么让用户访问到?第十二章:无服务器部署与 CI/CD 自动化 带你把项目部署上线。
