1. 从合并到提议:为什么需要 Pull Requests?
在上一节我们学会了在本地电脑上合并(merge)分支。独自工作时这很好用。但如果整个团队在做这个项目怎么办?如果每个人都把改动直接合并到主分支 main,很快就会乱套:有人可能会不小心提交有错误的代码、破坏构建或者删除同事的重要工作。
为避免这种情况,团队开发里有另一种做法。不是马上合并改动,而是创建一个合并提议。这个提议叫做 Pull Request(简称 PR),在有的平台上也叫 Merge Request。
Pull Request 是一个正式请求:“请把(pull)我在自己分支的改动拉过来并合并(merge)到主分支”。但这不仅仅是请求,它是一个讨论、审查和改进代码的场所,在代码进入 main 之前进行把关。
2. 使用 Pull Request 的标准工作流程
我们一步步看一下在创建新功能时典型的工作流程长什么样。
在创建新任务的分支之前,确认你已经把所有完成的提交 (push) 发上去,并且把主分支 main 更新了(Update Project)。
否则你那些“忘记”的本地提交会从 main 意外地进入新的 Pull Request,给同事们造成混乱。
第 1 步. 为新任务创建分支。
像以前一样,任何新工作都从创建一个独立分支开始。比如我们想给项目加一份贡献者指南文件,就创建分支 feature/add-contribution-guide。
第 2 步. 做改动并把你的分支推到 GitHub。
在新分支里创建文件 CONTRIBUTING.md(创建后按 Add),并写点给其他开发者的说明。然后做 Commit and Push,写清楚的提交信息,比如:docs: Add contribution guide。
这是关键一步! Pull Request 是基于已经存在于远程服务器的分支创建的。所以在创建 PR 之前,必须先把你的新分支 push 到 GitHub。
3. 在 IntelliJ IDEA 中创建 Pull Request
现在你的分支在 GitHub 上了,就可以创建 Pull Request。
第 1 步. 打开 Pull Requests 标签。
在 IDE 左侧有个 Pull Requests 标签。打开它,点 + 图标来新建 PR。
第 2 步. 填写 PR 信息。
IDE 会自动打开一个方便的界面来创建 Pull Request。你的任务是把它填好。我们来看看主要字段:
- 标题:IDE 常把分支名放这里,但那不是好习惯。标题要简短、清晰,反映改动的要点,就像好的提交信息一样。
- 描述:在这里解释你做了什么和为什么。
- Reviewers:在这里你选一个或多个同事来审查你的代码。在练习项目里可以跳过,但实际工作中这是必须的。
- Assignees:通常填你自己,表示你是作者并主要负责这项任务和在 review 后做改动。
所有字段填好后就可以放心点击 Create Pull Request。
4. 代码评审:检查与讨论
PR 创建后进入最重要的一环——代码评审 (code review)。同事可以打开你的 PR,查看所有改动并留下评论。
你可以在 IDE 的 Pull Requests 标签里看到所有讨论。如果有人留了评论,你会收到通知。
如果别人要求你修改怎么办?
很简单!不需要新开 PR。只要在同一个分支里做需要的改动,提交新的 commit 并 push。GitHub 上的 Pull Request 会自动更新,包含你新的提交。
5. 完成工作:合并并删除分支
当所有问题都解决并且团队批准你的改动后,就可以合并 Pull Request。通常是高级开发者来做,或者如果你有权限也可以自己合并。
第 1 步. Merge
合并通常在 GitHub 网站上完成。在你的 PR 下会出现一个绿色的大按钮 Merge pull request。点它后你的代码就成了主分支 main 的一部分。
第 2 步. 删除分支。
合并后你的 feature 分支就不需要了,删除它可以避免仓库混乱。GitHub 会提示你并显示 Delete branch 按钮。
别忘了也在本地 IDE 删除该分支,保持本地整洁。这可以通过分支管理菜单完成。
6. 三条提交规则
好的提交不仅仅是合适的信息,还要有正确的内容。为了让你的变更历史干净、有用、看起来专业,遵守下面三条简单规则。
规则 1:按规范写清楚的提交信息
你的提交是你发给团队和未来自己的消息。全是像 "fix" 或 "update" 这样的信息毫无用处。最流行的规范叫 Conventional Commits。它建议的结构是:
<type>: <short description>
Тип 是描述改动类型的短词:
feat: (feature) — 用于新功能。fix: — 用于修复 bug。docs: — 用于文档变更。style: — 用于格式调整,不影响代码逻辑。refactor: — 用于不增加功能也不修 bug 的代码重构。test: — 用于添加或修正测试。chore: — 用于与代码无关的日常任务(更新依赖、构建设置)。
示例:
- 不好:
fixed bug - 好:
fix: Correct user login validation
- 不好:
readme - 好:
docs: Update installation instructions
规则 2:一个提交——一个逻辑改动(原子性)
别试图在一个提交里同时修个 bug、加个功能、重构老代码。这样的提交很难审查,也几乎不可能在出问题时无痛回滚。
每个提交只解决一件具体的事情。
- 不好: 一个提交信息是 "Update user page",它同时添加了头像字段、修复了用户名校验 bug、还改了按钮颜色。
- 好: 三个不同的提交:
feat: Add avatar upload to user profilefix: Correct username validation logicstyle: Update button colors on user page
小而聚焦的提交更容易理解和管理。
Rule 3: Commit must not break the project
每个合并到主分支的提交都应该保持项目能运行。提交前你至少要确认代码可以编译。但是仅靠手动检查不够保险,怎么确认你没有意外破坏系统其他部分?
这时自动化就派上用场了。在本课程里我们不配置自动化流程,但你应该知道真实项目里是怎么做的。现在的团队用持续集成(Continuous Integration, CI),比如 GitHub Actions。
它怎么工作?
你写代码和测试,然后在 GitHub 上配置一个工作流程(workflow)。从此,每当你向 Pull Request push,魔法就发生了:
- GitHub Actions 监听到这个事件并运行你的工作流程。
- 它会自动“构建”项目并 运行所有测试。
- 如果所有测试通过,你的提交旁边会在 GitHub 上出现一个 绿色勾。这是给团队的信号:你的改动是安全的。
- 如果至少有一个测试失败,你会看到 红色叉。这种情况下绝对不能把 PR 合并到主分支。
Graph LR
Subgraph GitHub
A[Developer] -- "push" --> B(Repository)
B -- "Event: push" --> C{GitHub Actions}
end
Subgraph Workflow
C -- "Run" --> D[Running_tests]
D --> E[Success]
D --> F[Failed]
end
Subgraph Notifications
F --> G((Email))
G --> H[Developer]
G --> I[Team]
end
Style F fill:#f99,stroke:#333,stroke-width:2px
Style G fill:#ccf,stroke:#333,stroke-width:2px
你可以设置通知。当测试失败时,GitHub Actions 可以给你或整个团队发邮件。这种做法会培养一种文化:测试不是形式,而是开发的一部分,每个人都对自己代码的质量负责。
GO TO FULL VERSION