团队协作工作流
本章要点
- 主流的三种协作模型:GitHub Flow / Git Flow / GitLab Flow
- 各流程的适用场景与分支结构
- Pull Request / Merge Request 的完整流程
- Code Review 的最佳实践
- 团队 Git 规范建议(提交信息、分支命名、权限)
协作流程的两种基本模型
所有工作流都是下面两种原子操作的组合:
| 模型 | 做法 | 特点 |
|---|---|---|
| 共享分支(shared branch) | 所有人直接往同一分支 push | 简单,但冲突频繁、难以保护 |
| 分支 + 合并请求(PR/MR) | 各自在分支开发,通过 Pull Request 审核后合入 | 有审核关卡,适合中大型团队/开源 |
现代团队几乎都采用"受保护的主分支 + 功能分支 + PR 审核"的组合。
GitHub Flow(最简单,推荐大多数团队)
只有一条长期分支 main,加上短命的特性分支:
text
main ────────────────────────────────────
└─ feat/xxx ─ feat/xxx'(PR 合入)
└─ fix/yyy ─ fix/yyy'(PR 合入)流程
text
1. 从 main 拉一条分支:git switch -c feat/xxx
2. 小步提交,及时 push:git push -u origin feat/xxx
3. 发起 Pull Request(PR)
4. 通过 CI 检查 + 至少 1 人 Code Review
5. 合入 main(通常是 squash merge 或 rebase merge)
6. 删除特性分支适用场景
- 持续部署(随时可从 main 发布)的互联网团队
- 中小团队,流程越简单越好
- 规则:main 始终可发布;分支短命(几小时到几天)
Git Flow(经典但较重)
由 Vincent Driessen 提出,分支职责分明:
text
release 分支: 发布准备(只修 bug,打标签后并入 main 和 develop)
│
main ────────●(v1.0)────────●(v1.1)────── ← 只存已发布版本 + 标签
│ │ │
develop ──────┼──────────────┼────────────── ← 日常集成主线
│ │ │
feature/xxx ──┘ │ ← 新功能从 develop 拉出
│ │
hotfix/yyy ──────────────────┘ ← 紧急修复从 main 拉出| 分支 | 职责 | 从哪来 | 合到哪 |
|---|---|---|---|
main | 正式发布版本,只接受标签 | — | — |
develop | 日常开发集成线 | main | main(发布时) |
feature/* | 新功能 | develop | develop |
release/* | 发布准备(稳定、修 bug) | develop | main + develop |
hotfix/* | 线上紧急修复 | main | main + develop |
适用场景
- 需要明确版本管理、计划性发布的团队(如传统软件、游戏、移动端发版)
- ⚠️ 缺点:分支多、流程重,持续部署团队往往觉得繁琐
GitLab Flow(折中方案)
GitLab 提出的实践,核心思想:
- 环境分支:
main(开发)→pre-production(预发)→production(生产),代码从左往右流动。 - 功能分支:从
main拉出,PR 合回main。 - 发布分支:按需从 main 拉出维护旧版本。
- 结合"环境部署"概念:合入特定分支即触发对应环境的部署。
适用:需要多环境(测试/预发/生产)管理的团队,介于 GitHub Flow 与 Git Flow 之间。
Pull Request(PR)全流程实战
第一步:从最新 main 拉分支
bash
$ git switch main
$ git pull # 确保基于最新代码
$ git switch -c feat/user-profile # 命名规范:feat/、fix/、docs/、refactor/第二步:开发与提交
bash
$ git add -p # 分块暂存,保持提交干净
$ git commit -m "feat(user-profile): 增加资料编辑功能"
# 小步提交:一个逻辑 = 一个提交
$ git push -u origin feat/user-profile第三步:发起 PR
在 GitHub/GitLab 界面操作:
- 标题:一句话说清"做了什么"(可带前缀,如
feat: xxx) - 描述:背景、改动内容、测试情况、关联 Issue(
Closes #123) - 目标分支:确认是合并到
main/develop
第四步:等待 CI 与 Review
- CI(持续集成):提交后自动跑测试/构建,红灯则先修。
- Code Review:评审人提意见 → 你修改 → 追加提交 → 评审人确认。
第五步:处理评审意见
bash
$ git add . && git commit -m "fix(user-profile): 按评审意见调整表单校验"
$ git push # PR 自动更新💡 评审期间如果 main 有新提交,PR 会显示冲突。解决:
bash$ git switch main && git pull $ git switch feat/user-profile $ git merge main # 或 git rebase main(取决于团队约定) $ git push
第六步:合入
常见三种合入方式(团队约定其一):
| 方式 | 效果 | 适用 |
|---|---|---|
| Merge commit | 保留所有提交 + 一个合并提交 | 想完整保留开发历史 |
| Squash and merge | 所有提交压成一个合入 main | 特性分支提交较碎时(最常见) |
| Rebase and merge | 提交原样线性排列 | 想保持线性且提交本身很整洁 |
第七步:删除分支
bash
$ git switch main && git pull
$ git branch -d feat/user-profile # 本地
# 远程分支在 PR 合入后由平台自动删除(或手动删)Code Review 最佳实践
提交者的责任
- PR 尽量小:一个 PR 只做一件事,改动量控制在可审范围(几百行以内)。
- 提交信息规范,PR 描述写清"为什么"。
- 自己先 review 一遍自己的 diff,去掉调试代码、
console.log。 - 及时回应评审意见。
评审者的责任
- 关注设计正确性,而不是逐字符挑刺。
- 肯定好的写法(让作者有反馈循环)。
- 用问题代替命令:"这里为什么不用 X?" 而不是 "改成 X"。
- 区分"必须改"(阻塞合入)与"建议"(可后续跟进)。
团队 Git 规范建议模板
text
# 分支命名
feature/功能名 # 新功能
fix/bug简述 # bug 修复
hotfix/紧急修复名 # 线上紧急修复
release/版本号 # 发布准备
docs/说明 # 文档
# 提交信息(约定式提交)
feat(模块): 说明
fix(模块): 说明
refactor(模块): 说明
...
# 规则
1. main/develop 分支受保护:禁止直接 push,必须走 PR
2. PR 必须通过 CI 且至少 1 人 review
3. 提交要小而完整,禁止提交密钥/依赖目录
4. 合入采用 squash merge(或团队约定的一种)
5. 发布用 tag 标记:v主版本.次版本.修订号受保护分支配置
在 GitHub/GitLab 设置中把 main/develop 设为受保护:
- 禁止直接 push(只能通过 PR)
- 要求 PR 前 CI 通过
- 要求至少 N 个批准
- 合入后自动删除源分支
开源协作:Fork + PR 模式
text
上游仓库 upstream ──fork──► 你的远程 origin
│ clone
▼
本地仓库
│ push
▼
你的远程 origin ──PR──► 上游仓库bash
$ git clone https://github.com/你的账号/项目.git
$ git remote add upstream https://github.com/原作者/项目.git
$ git fetch upstream
$ git switch -c fix/xxx upstream/main # 基于上游最新代码开发
# ...提交、推送...
$ git push origin fix/xxx # 推到自己 fork
# 在平台上从"你的 fork 的分支"发起 PR 到"上游 main"保持 fork 同步:
bash
$ git fetch upstream
$ git merge upstream/main # 把上游更新并入自己的 main
$ git push origin main