【Git 精品详解】多人协作:角色分工、Fork + PR 工作流、Code Review 流程、合并策略对比、commit message 规范、复杂冲突解决

Git 多人协作实战:从单兵作战到团队配合

在这里插入图片描述

🌈 say-fall:个人主页
🚀 专栏:《手把手教你学会C++》 | 《系统深入Linux操作系统》 | 《数据结构与算法》 | 《小游戏与项目》
💪 格言:做好你自己,才能吸引更多人,与他们共赢,这才是最好的成长方式。

📝 前言

如果说第 1-3 篇是"个人武功秘籍",那这一篇就是"团队作战兵法"。

前 3 篇你已经掌握了:

  • ✅ 本地仓库的"增删改查"
  • ✅ 分支的创建、合并、冲突解决
  • ✅ 远程推送、拉取、SSH 免密

但当你真正加入一个 5 人、10 人甚至 100 人的团队时,会发现

  • 同事 push 了一个 commit,你的本地突然"过期"了
  • 你的 PR 评审被退回 3 次
  • 改了一行代码,要不要直接 push ?
  • “我们组用 squash merge 还是 rebase merge?”
  • “为什么我 pull 之后代码不见了?”

这些"团队协作"的坑,教材上几乎不教,但每个程序员入职第一周都会踩。

本篇我们就把这些坑讲透。从角色分工讲起,Fork + PR 工作流Code Review 流程合并策略对比commit message 规范复杂冲突解决,最后用5 人团队协作实战把所有知识串起来。

🎯 本节目标:让你具备团队协作的工程能力。学完之后,你能在多人项目里流畅地"提交 PR、通过 review、解决冲突、合并代码",并能理解团队为什么选择这种工作流

通过本文,你将掌握:

技能应用场景
理解团队角色与责任划分知道自己的"位置"
玩转 Fork + Pull Request 工作流开源贡献、入职第一周
区分 merge / squash / rebase 合并策略选对合并方式
进行规范的 Code Review提升代码质量
写出规范的 commit message让历史可读
解决复杂多人冲突团队协作必修课
模拟 5 人团队完整协作实战出真知

📌 前置知识: 熟练掌握第 1-3 篇。本篇命令同样在 user@localhost 虚拟环境下演示。

文章目录


一、👥 多人协作的核心:理解角色与流程

1.1 团队里都有哪些角色

在 5-10 人的研发团队里,Git 操作的角色通常分这几类:

角色Git 操作权限主要责任
项目维护者(Maintainer)直接 push 到 master合并 PR、发布版本、处理 issue
核心开发者(Core Dev)push 到 develop 等开发分支功能开发、Code Review
普通开发者(Dev)只能在自己 fork 或 feature 分支提交 PR、参与 Review
外部贡献者(Contributor)fork 仓库后提 PR提交 patch、提 issue
代码审查者(Reviewer)读权限 + 评论权限评审 PR、提出改进意见

💡 一个开发者可以身兼多职——小公司里"开发 + 维护者"是常态。但 Git 权限模型是一样的。

1.2 典型协作流程(5 人团队)

        ┌──────────┐
        │  维护者   │
        │ (Maintainer) │
        └─────┬────┘
              │ 审核
              ▼
   ┌─────────────────────┐
   │   Code Review 流程   │
   │ (核心开发者 + 审查者) │
   └─────┬───────────────┘
         │ 通过
         ▼
   ┌─────────────────────┐
   │   合并到 develop/master │
   └─────────────────────┘
         ▲
         │ PR
   ┌─────┴───────────────┐
   │   开发者 (Dev)        │
   │ - 拉取最新代码        │
   │ - 创建 feature 分支   │
   │ - 提交 commit        │
   │ - 推送 + 创建 PR     │
   └─────────────────────┘

5 人团队的典型一天

时间角色动作
09:00所有人git pull 拉取最新代码
09:30Dev A创建 feature/login 分支,开发
10:00Dev B修 Bug,创建 hotfix/pay 分支
11:00Dev A完成功能,push + 创建 PR
11:30Reviewer评审 Dev A 的 PR,留下评论
14:00Dev A根据评论修改,push 新的 commit
15:00Reviewer再次评审,通过
15:30Maintainer把 PR 合并到 develop
16:00Dev B修完 Bug,提 PR,被合并

1.3 协作的本质

💡 多人协作的本质让多个人的 commit 安全、可追溯地汇聚到同一棵版本树上

围绕这个本质,团队要解决 4 个核心问题:

  1. 谁有权合并?(权限管理)
  2. 合并前谁来看?(Code Review)
  3. 用什么方式合并?(merge / squash / rebase)
  4. 出冲突了怎么办?(冲突解决流程)

接下来我们就一个一个讲透。


二、🌿 Fork + Pull Request:开源协作主流

2.1 什么是 Fork

💡 Fork(分叉) 是 GitHub/Gitee 提供的一个按钮:在你的账号下复制一份别人的仓库

# 你不需要在本地执行 git fork
# 这是一个平台操作
# 1. 在 Gitee/GitHub 打开别人仓库
# 2. 点右上角 "Fork" 按钮
# 3. 你账号下出现一份完整副本

Fork 后,你和原仓库完全独立——你随便改,不会影响原仓库。

2.2 什么是 Pull Request

💡 Pull Request(PR,拉取请求) 是"请求原仓库拉取你的改动"。

流程:

  1. 你在 fork 仓库里改代码
  2. 你创建一个 PR:“请把我的改动合并到原仓库”
  3. 原仓库的维护者 review 你的代码
  4. 维护者合并你的 PR

这是开源协作的黄金标准——任何人都能为开源项目贡献代码,但没有维护者的允许,你的代码永远不会进入主仓库

2.3 Fork + PR 完整流程

# 1. 在 Gitee/GitHub 上 fork 原仓库
# 假设原仓库: https://gitee.com/upstream/popular-project.git
# fork 后: https://gitee.com/your-name/popular-project.git

# 2. 克隆你的 fork 到本地
git clone https://gitee.com/your-name/popular-project.git
cd popular-project

# 3. 添加原仓库为 upstream(上游)
git remote add upstream https://gitee.com/upstream/popular-project.git

# 4. 验证远程
git remote -v
# origin    https://gitee.com/your-name/popular-project.git (fetch)
# origin    https://gitee.com/your-name/popular-project.git (push)
# upstream  https://gitee.com/upstream/popular-project.git (fetch)
# upstream  https://gitee.com/upstream/popular-project.git (push)

# 5. 同步原仓库最新代码
git fetch upstream
git checkout master
git merge upstream/master

# 6. 创建 feature 分支
git checkout -b feature/awesome-improvement

# 7. 修改代码
echo "improvement" > improvement.md
git add .
git commit -m "feat: 添加 awesome-improvement"

# 8. 推送到自己的 fork
git push origin feature/awesome-improvement

# 9. 在 Gitee/GitHub 上点 "创建 Pull Request" 按钮
# - base: upstream/master
# - compare: your-name/feature/awesome-improvement
# 填写 PR 标题、描述
# 提交!

2.4 同步上游最新代码

关键问题:你提 PR 期间,原仓库可能已经更新。

# 1. 拉取上游最新
git fetch upstream

# 2. 切到 master 同步
git checkout master
git merge upstream/master

# 3. 切到你的 feature 分支
git checkout feature/awesome-improvement

# 4. 把 master 的更新合并到 feature
git merge master
# 或更推荐:rebase
git rebase master

# 5. 解决可能的冲突

# 6. 强制 push 到你的 fork(rebase 后需要)
git push --force-with-lease origin feature/awesome-improvement

💡 rebase 而不是 merge——这样你的 feature 分支历史是线性的,PR 更干净。

2.5 团队内部也用 Fork + PR 吗?

不一定。两种模式各有适用场景:

模式适用优点缺点
共享仓库 + 分支团队成员都能 push 到主仓库简单、速度快权限控制弱
Fork + PR权限严格的开源/企业项目权限隔离清晰流程繁琐

💡 国内中小公司用"共享仓库 + 分支"的居多。大厂、外企、开源项目用"Fork + PR"为主。

2.6 实战:给"假想开源项目"提 PR

# 假设我们要给 "git-practice" 这个开源项目修一个 typo
# 1. fork
# 2. clone fork
git clone git@gitee.com:your-name/git-practice.git
cd git-practice

# 3. 配 upstream
git remote add upstream git@gitee.com:original/git-practice.git

# 4. 同步最新
git fetch upstream
git checkout master
git merge upstream/master

# 5. 创建分支
git checkout -b fix/readme-typo

# 6. 修 typo
echo "# Git 练习项目" > ReadMe  # 假设原 ReadMe 写错了
git add .
git commit -m "fix: 修正 ReadMe 中的拼写错误"

# 7. push 到 fork
git push origin fix/readme-typo

# 8. 平台操作:点 "Create Pull Request"

这就是完整的开源贡献流程。


三、🔀 合并策略:merge / squash / rebase

PR 通过后,用什么方式合并到主分支?这又是一个团队要统一的事。

3.1 三种合并方式

合并方式行为历史形态适合
Merge Commit保留所有 commit + 1 个 merge commit树状分叉长期 feature 分支
Squash and Merge把所有 commit 合并成 1 个直线短生命周期 PR
Rebase and Merge把所有 commit "重放"到目标分支直线干净的小功能

3.2 Merge Commit 详解

# 保留所有 commit
git merge --no-ff feature/login

结果

*   9a8b7c6 (HEAD -> master) Merge branch 'feature/login'
|\
| * a1b2c3d feat: 登录接口
| * d4e5f6g fix: 登录bug
| * h7i8j9k docs: 登录文档
|/
* 0l1m2n3 init: 项目初始化

优点

  • 完整保留 feature 分支的所有 commit
  • 历史可追溯,"这次功能包含哪些 commit"一目了然
  • git log --graph 能看到完整分支结构

缺点

  • 历史上多一个 merge commit
  • feature 分支里的 commit 不够"原子"

3.3 Squash and Merge 详解

# 把所有 commit 压缩成 1 个
git merge --squash feature/login
git commit -m "feat: 完整登录功能"

结果

* a1b2c3d (HEAD -> master) feat: 完整登录功能
* 0l1m2n3 init: 项目初始化

优点

  • 历史干净,1 个 PR = 1 个 commit
  • master 分支历史线性、可读
  • 适合"功能 PR"

缺点

  • 丢失了 feature 分支里的中间 commit 信息
  • 出问题不好定位"具体哪个 commit 出错"

3.4 Rebase and Merge 详解

# 把 feature 分支 rebase 到 master 最新,再 fast-forward
git rebase master
git checkout master
git merge feature/login  # 这时是 fast-forward

结果

* a1b2c3d (HEAD -> master, feature/login) feat: 登录接口
* d4e5f6g fix: 登录bug
* h7i8j9k docs: 登录文档
* 0l1m2n3 init: 项目初始化

优点

  • 保留所有 commit 信息
  • 历史线性、干净
  • 出问题可以精确回退到某个 commit

缺点

  • 重写了 commit id(“看起来像新 commit”)
  • 改写历史,不能用于已 push 到共享仓库的 commit

3.5 团队怎么选?

团队类型推荐
大厂 / 严肃开源项目Squash and Merge(默认)+ Rebase(高级)
中小公司 / 内部项目Merge Commit(默认)
个人 / 试验性项目看心情

💡 最重要的不是用哪种,而是团队统一——用哪一种都行,别混着用

3.6 GitHub/Gitee 平台的合并按钮

主流平台都提供这三种按钮:

Pull Request 页面:
  [Merge pull request]    ← Merge Commit
  [Squash and merge]      ← Squash
  [Rebase and merge]      ← Rebase

通常默认 Squash,因为最干净。


四、📝 Code Review:提升代码质量的协作

4.1 什么是 Code Review

💡 Code Review(代码审查) 是让别人在你合并代码前,先看一眼你的改动。

目的不是"挑刺",而是:

  • 发现 bug:自己写的代码,自己看 3 遍也未必能发现
  • 统一风格:让团队代码风格一致
  • 知识共享:让团队成员互相学习
  • 避免风险:防止"看起来能跑"但有安全/性能问题

4.2 Code Review 的常见流程

开发者 A 提交 PR
    ↓
Reviewer B 收到通知,打开 PR 页面
    ↓
Reviewer 逐文件查看 diff
    ↓
留下评论:
  - ✅ LGTM(Looks Good To Me)
  - 💬 建议:这里可以拆成函数
  - ❌ 这个变量名有歧义,建议改
  - ❌ 这里没考虑空指针情况
    ↓
开发者 A 根据评论修改
    ↓
Reviewer 二次 review
    ↓
通过 ✅
    ↓
维护者合并

4.3 Reviewer 该看什么

维度检查点
正确性逻辑对不对?边界条件?异常处理?
可读性命名清晰?注释充分?结构合理?
性能有没有 O(n²) 的循环?N+1 查询?
安全SQL 注入?XSS?硬编码密钥?
可维护性重复代码?过度设计?耦合?
测试有没有单元测试?测试覆盖度?
文档README 更新?CHANGELOG 加了?

4.4 提 PR 的人该做什么

# 1. PR 标题要清晰
"feat: 添加用户登录功能"    # ✅
"fix: 修了一些东西"        # ❌

# 2. PR 描述要有上下文
"## 改动说明
- 添加了登录功能
- 用了 JWT 鉴权
- 单元测试覆盖 80%

## 测试
- [x] 单元测试通过
- [x] 手动测试通过

## 关联 Issue
Closes #123"

# 3. 改动要小而专注
一个 PR 只做一件事    # ✅
一个 PR 改 30 个文件  # ❌(review 的人会哭)

💡 "小 PR + 高频次"是黄金法则。大 PR review 质量低,bug 容易漏。

4.5 Reviewer 怎么提意见

好的评论:

💬 这里的 if/else 嵌套太深,建议用 early return:
  if (user == null) return;
  if (!user.active) return;
  // 主要逻辑

不好的评论:

❌ 这段代码写得很烂,建议重写。

原则

  • 对事不对人(“这段代码"而不是"你写的”)
  • 提具体建议(不要只说"不好")
  • 解释为什么(“避免空指针”)
  • 区分"必须改"和"建议改"(用 nit:suggestion: 前缀)

4.6 实战:一次完整的 PR 评审

# Dev A 完成功能后
git add .
git commit -m "feat(login): 添加 JWT 登录"
git push origin feature/login

# 在 Gitee 上点 "创建 Pull Request"
# 填写 PR 标题、描述、关联 Issue

# Reviewer B 收到通知
# 在 PR 页面查看 diff,留下评论:
#   "建议把 password 字段加上 @NotBlank 校验"
#   "JWT 过期时间建议改成 2 小时(默认 24h 太长)"

# Dev A 看到评论,修改
vim LoginRequest.java
# 添加校验
vim SecurityConfig.java
# 改过期时间
git add .
git commit -m "refactor(login): 根据 review 调整"
git push origin feature/login

# Reviewer B 二次 review,看到改动已包含
# 留下 "LGTM 👍"

# Maintainer 合并
# 点击 "Squash and merge" 按钮

这就是真实的"提 PR → 评审 → 修改 → 合并"全流程。


五、📋 协作规范:commit message 与 branch 命名

5.1 为什么需要规范

没规范 = 灾难现场

git log --oneline
fix bug
update
改了
test
asdf

看着头疼不?规范不是装腔作势,是救命

5.2 主流 commit message 规范:Conventional Commits

💡 Conventional Commits 是目前最流行的 commit message 规范,被 Vue、Angular 等知名项目采用。

格式:

<type>(<scope>): <subject>

<body>

<footer>

type 类型:

type含义
feat新功能
fix修 bug
docs文档改动
style格式调整(不影响代码运行)
refactor重构(既不是新功能也不是修 bug)
perf性能优化
test测试相关
chore构建/工具/依赖变更

示例:

# 好的 commit message
git commit -m "feat(login): 添加 JWT 鉴权"
git commit -m "fix(pay): 修复金额为 0 时崩溃的 Bug"
git commit -m "docs(readme): 更新部署说明"
git commit -m "refactor(user): 拆分 UserService"

# 不好的 commit message
git commit -m "fix bug"
git commit -m "update"
git commit -m "改了"

5.3 复杂 commit 示例

feat(login): 添加 JWT 鉴权

- 使用 jjwt 0.11.5 库
- Token 过期时间 2 小时
- 增加 refresh token 机制

Closes #123
Reviewed-by: zhangsan

字段说明:

  • 第一行:简短描述(50 字符内)
  • 空行
  • 详细说明:为什么改、改了什么
  • 关联 Issue:Closes #123
  • 评审人:Reviewed-by:

5.4 用工具自动生成规范的 commit message

# 安装 commitizen(交互式写 commit message)
npm install -g commitizen
# 或
pip install -U commitizen

# 使用
git cz
# 交互式选择 type、scope、subject

5.5 Branch 命名规范

推荐的命名规范:

类型格式示例
功能分支<type>/<short-desc>feature/user-loginfeat/shopping-cart
Bug 修复fix/<short-desc>fix/login-bugfix/pay-crash
紧急修复hotfix/<short-desc>hotfix/pay-2024-09
预发布release/<version>release/v1.0.0
个人开发<dev-name>/<short-desc>zhangsan/feature-x

示例:

# 好
git checkout -b feature/user-login
git checkout -b fix/login-validation-bug
git checkout -b release/v1.2.0

# 不好
git checkout -b my-branch
git checkout -b test
git checkout -b tmp

⚠️ 永远不要 push 一个叫 testtmpfix 的分支——团队成员看到会一脸懵。

5.6 实战:用 commitizen 写规范 commit

# 1. 安装
npm install -g commitizen cz-conventional-changelog

# 2. 项目初始化
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

# 3. 使用
git add .
git cz
# ? Select the type of change that you're committing: feat
# ? What is the scope of this change (e.g. component or file name): login
# ? Write a short, imperative tense description: 添加 JWT 鉴权
# ? Provide a longer description: 
# ? Are there any breaking changes? No

# 自动生成:
# feat(login): 添加 JWT 鉴权

六、🛠️ 复杂冲突解决:rebase / rerere / reflog 实战

团队协作里,真正让人抓狂的冲突长什么样?我们来看。

6.1 复杂冲突场景

场景:5 人同时开发,A 和 B 改了同一文件的同一函数的不同部分。

master: C0 ── C1
A 的分支:   C1 ── C2'  (改了函数 1)
B 的分支:   C1 ── C2'' (改了函数 2)

当 B 把 master 拉过来时:冲突只发生在同一文件的同一行吗?不一定——可能是同一文件的不同函数

Git 默认按行检测冲突,但其实整段函数都可能被标记为冲突

6.2 用 merge 解决 vs 用 rebase 解决

方式行为历史
git merge一次合并,可能产生 merge commit保留分叉
git rebase"重放"你的 commit 到目标分支最新变线性

推荐 rebase 保持历史干净

# 1. 切到 feature 分支
git checkout feature/login

# 2. rebase master
git rebase master

# 3. 解决冲突
# vim app.py
git add app.py
git rebase --continue

# 4. 切回 master 合并
git checkout master
git merge feature/login  # fast-forward

⚠️ rebase 不能用于已 push 的共享分支——会改写历史,让队友"脱节"。

6.3 取消 rebase

# rebase 中遇到问题想撤销
git rebase --abort

6.4 用 rerere 解决重复冲突

rerere = reuse recorded resolution。它会记住你的冲突解决方案,下次再遇到同样冲突自动应用。

# 1. 开启 rerere(默认是开着的)
git config --global rerere.enabled true

# 2. 第一次遇到冲突,手动解决
git add app.py
git commit -m "resolve conflict"

# 3. 下次遇到同样的冲突
# Git 会自动用上次的解决方案!

💡 rerere 是大型团队的"救星"——长期维护的 feature 分支会反复遇到同样冲突,rerere 能节省大量时间。

6.5 用 reflog 找回"消失"的代码

场景:你 rebase 错了,或者 reset 错了,commit 突然不见了

# 1. 看所有操作记录
git reflog

# 输出:
# abc1234 HEAD@{0}: rebase finished: refs/heads/feature/login onto def5678
# def5678 HEAD@{1}: rebase: checkout def5678
# 0l1m2n3 HEAD@{2}: commit: my changes  ← 这个!我的代码!

# 2. 找回去
git reset --hard 0l1m2n3

💡 reflog 是 Git 里的"后悔药"——只要 commit 还在 reflog 里,几乎都能找回来

6.6 复杂冲突的实战工作流

# 场景:feature 分支领先 master 5 个 commit
# master 上有人 push 了冲突的改动

# 1. 切到 feature 分支
git checkout feature/pay

# 2. fetch + rebase
git fetch origin
git rebase origin/master

# 3. 解决冲突(Git 会暂停在第一个冲突)
# 打开文件,看到冲突标记:
# <<<<<<< HEAD
# 你的代码
# =======
# 别人的代码
# >>>>>>> origin/master
# 手动编辑,保留两边的合理部分

git add app.py
git rebase --continue

# 4. 重复步骤 3 直到所有冲突解决

# 5. 回到 master 合并
git checkout master
git merge feature/pay  # 这次是 fast-forward

# 6. push
git push origin master

这就是"专业开发者"解决冲突的标准流程


七、🎯 5 人团队协作实战演示

把所有知识点串起来。我们模拟一个 5 人团队的开发场景。

7.1 准备工作

# 准备一个"远程"仓库(用本地 bare 仓库模拟)
mkdir -p /home/user/test/team-workflow
cd /home/user/test/team-workflow
git init --bare shared-repo.git

# 5 个人各自 clone 一份
for i in 1 2 3 4 5; do
    git clone /home/user/test/team-workflow/shared-repo.git dev$i
    cd dev$i
    git config user.email "dev$i@example.com"
    git config user.name "Dev $i"
    cd ..
done

# dev1 模拟项目维护者,初始化仓库
cd dev1
echo "v1.0.0" > app.py
git add .
git commit -m "feat: 项目初始化 v1.0.0"
git push origin master
cd ..

7.2 多人并行开发

# ====== Dev 1(维护者):开始新功能 ======
cd dev1
git checkout -b feature/user-auth
echo "def login(): pass" > auth.py
git add .
git commit -m "feat(auth): 添加登录函数"
git push -u origin feature/user-auth

# ====== Dev 2:修 Bug ======
cd /home/user/test/team-workflow/dev2
git pull origin master
git checkout -b fix/pay-bug
echo "def pay(): pass" > pay.py
git add .
git commit -m "fix(pay): 修复付款 Bug"
git push -u origin fix/pay-bug

# ====== Dev 3:开发新功能 ======
cd /home/user/test/team-workflow/dev3
git pull origin master
git checkout -b feature/notification
echo "def notify(): pass" > notify.py
git add .
git commit -m "feat(notify): 添加通知模块"
git push -u origin feature/notification

# ====== Dev 4:开发新功能(修改同一文件) ======
cd /home/user/test/team-workflow/dev4
git pull origin master
git checkout -b feature/pay-v2
echo "def pay_v2(): pass" > pay.py
git add .
git commit -m "feat(pay): 添加 pay_v2 升级版"
git push -u origin feature/pay-v2

# ====== Dev 5:暂时摸鱼 ======
echo "Dev 5 摸鱼中..."

7.3 Dev 1 完成开发并提 PR

# 回到 Dev 1
cd /home/user/test/team-workflow/dev1
git checkout feature/user-auth
# (真实场景:在 Gitee/GitHub 上创建 PR)
# 这里我们直接合并到 master 模拟

# 切回 master
git checkout master
git pull origin master  # 拉取其他人的分支信息
git merge --no-ff -m "merge feature/user-auth" feature/user-auth
git push origin master

7.4 合并 Dev 2 的 PR

# Dev 1 作为维护者,合并 Dev 2 的 PR
cd /home/user/test/team-workflow/dev1
git checkout master
git pull origin master

# 评审 Dev 2 的代码(这里直接合并)
git merge --no-ff -m "merge fix/pay-bug" origin/fix/pay-bug
git push origin master

7.5 Dev 4 遇到冲突

# Dev 4 准备合并
cd /home/user/test/team-workflow/dev4
git checkout feature/pay-v2

# 拉取最新
git fetch origin

# 尝试 rebase
git rebase origin/master
# CONFLICT 提示(pay.py 被 Dev 2 也改了)

# 解决冲突
cat pay.py
# <<<<<<< HEAD
# def pay_v2(): pass
# =======
# def pay(): pass
# >>>>>>> origin/master
# 保留两者的功能(合并):
echo "def pay(): pass" > pay.py
echo "def pay_v2(): pass" >> pay.py

git add pay.py
git rebase --continue

# 推回 fork(用 --force-with-lease)
git push --force-with-lease origin feature/pay-v2

7.6 Dev 3 的 PR 被合并

# Dev 1 合并 Dev 3 的 PR
cd /home/user/test/team-workflow/dev1
git checkout master
git pull origin master
git merge --no-ff -m "merge feature/notification" origin/feature/notification
git push origin master

7.7 Dev 4 合并到 master

# Dev 1 合并 Dev 4 的 PR
cd /home/user/test/team-workflow/dev1
git checkout master
git pull origin master
git merge --no-ff -m "merge feature/pay-v2" origin/feature/pay-v2
git push origin master

# 打 tag 标记版本
git tag v1.1.0
git push origin v1.1.0

7.8 查看最终历史

# Dev 1 看完整历史
cd /home/user/test/team-workflow/dev1
git log --graph --pretty=format:'%h -%d %s (%cr) <%an>' --abbrev-commit

输出类似:

*   c9d8e7f - (HEAD -> master, tag: v1.1.0, origin/master) merge feature/pay-v2 (2 hours ago) <Dev 1>
|\
| * a1b2c3d - (origin/feature/pay-v2) feat(pay): 添加 pay_v2 升级版 (2 hours ago) <Dev 4>
|/
*   d4e5f6g - merge feature/notification (2 hours ago) <Dev 1>
|\
| * h7i8j9k - (origin/feature/notification) feat(notify): 添加通知模块 (2 hours ago) <Dev 3>
|/
*   l0m1n2o - merge fix/pay-bug (2 hours ago) <Dev 1>
|\
| * p3q4r5s - (origin/fix/pay-bug) fix(pay): 修复付款 Bug (3 hours ago) <Dev 2>
|/
*   t6u7v8w - merge feature/user-auth (3 hours ago) <Dev 1>
|\
| * x9y0z1a - (origin/feature/user-auth) feat(auth): 添加登录函数 (4 hours ago) <Dev 1>
|/
* b2c3d4e - feat: 项目初始化 v1.0.0 (4 hours ago) <Dev 1>

看到这个图,团队里每个人做了什么、什么时候合的、什么版本发布——一目了然。

这就是 5 人团队 Git 协作的"日常"。


八、❓ 本节常见问题解答

本节挑几个多人协作里最常被问到的问题。

1️⃣ 改了一行代码,要不要直接 push?

答:看团队规范和改动大小。

改动大小建议
一行注释/格式化可以直接 push
一个完整功能必须 PR + Review
紧急修复hotfix 分支 + 快速 PR

💡 改一行就 push,review 成本太低、不必要。但养成"小步快跑"的习惯是好事。

2️⃣ PR 被退回怎么办?

答:别玻璃心,理性面对。

  1. 认真看 review 评论——大多数 review 都是建设性的
  2. 逐条回复——用 commit 或评论回复每条建议
  3. 不认同时礼貌讨论——可以说"我有不同考虑,因为…"
  4. 修改后再次 push——PR 会自动更新

💡 被 review 退回 3 次以上是正常的。这正是 review 的价值——避免你的代码上线后才发现问题。

3️⃣ 我应该在 master 上开发吗?

答:不应该。

master 应该永远保持可发布状态。所有改动都在 feature/fix 分支上做,通过 PR 合并。

# 错误:直接在 master 上改
git checkout master
echo "bug fix" >> app.py
git add .
git commit -m "fix"
git push origin master  # 风险高!

# 正确:feature 分支 + PR
git checkout -b fix/some-bug
echo "bug fix" >> app.py
git add .
git commit -m "fix"
git push origin fix/some-bug
# 创建 PR

4️⃣ 怎么减少冲突?

答:5 个实用技巧。

  1. 频繁 pullgit pull --rebase 每天至少 2 次
  2. 小颗粒度 commit:不要攒几天一次性提交
  3. 不长时间维护同一分支:feature 分支越短命越不容易冲突
  4. 明确分工:避免两人改同一文件
  5. 及时 rebase:pull 之后 rebase 到最新

💡 冲突 = 沟通成本。减少冲突 = 减少沟通。但有些冲突不可避免——遇到就解决,别怕冲突

5️⃣ 队友的 commit 信息乱写,我管吗?

答:管,但用规范约束而不是批评。

# 1. 团队统一 commit 规范(参考第 5 节)
# 2. 用 commitlint 工具强制检查
npm install --save-dev @commitlint/cli @commitlint/config-conventional

# .commitlintrc.js
module.exports = { extends: ['@commitlint/config-conventional'] }

# 3. 用 husky 在 commit 时自动检查
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

配置好后,写"乱七八糟的 commit message"会被直接拒绝


九、🎯 实战练习:5 人协作"模拟器"

来一个完整练习,5 个"角色"在同一目录下协作(用临时目录模拟多人)。

任务

  1. 创建 team-repo 作为远程 bare 仓库
  2. 3 个目录模拟 3 个开发者,各自 clone
  3. Dev A 在 master 上加一个 auth.py
  4. Dev B 创建 feature/pay 分支,加 pay.py
  5. Dev C 创建 feature/pay 分支,加 pay.py和 Dev B 冲突
  6. 模拟 Dev B 先 push
  7. Dev C pull + rebase + 解决冲突
  8. 把 Dev C 的分支合并到 master

参考答案

# 1. 准备
mkdir -p /home/user/test/team-practice
cd /home/user/test/team-practice
git init --bare shared.git

# 2. 3 个开发者 clone
for i in A B C; do
    cd /home/user/test/team-practice
    git clone shared.git dev-$i
    cd dev-$i
    git config user.email "$i@example.com"
    git config user.name "Dev $i"
done

# 3. Dev A 初始化
cd /home/user/test/team-practice/dev-A
echo "def login(): pass" > auth.py
git add .
git commit -m "feat: 添加 auth 模块"
git push -u origin master

# 4. Dev B 和 C 拉取最新
cd /home/user/test/team-practice/dev-B
git pull origin master
cd /home/user/test/team-practice/dev-C
git pull origin master

# 5. Dev B 创建 feature/pay
cd /home/user/test/team-practice/dev-B
git checkout -b feature/pay
echo "def pay(): pass" > pay.py
git add .
git commit -m "feat(pay): B 添加付款"
git push -u origin feature/pay

# 6. Dev C 也创建 feature/pay(**注意:在自己的分支上**)
cd /home/user/test/team-practice/dev-C
git checkout -b feature/pay
echo "def pay_v2(): pass" > pay.py
git add .
git commit -m "feat(pay): C 添加 pay_v2"
git push -u origin feature/pay

# 7. Dev C 拉取 Dev B 的提交
git fetch origin
git rebase origin/feature/pay
# CONFLICT 提示

# 8. Dev C 解决冲突
echo "def pay(): pass" > pay.py
echo "def pay_v2(): pass" >> pay.py
git add pay.py
git rebase --continue

# 9. 推回
git push --force-with-lease origin feature/pay

# 10. 模拟维护者合并
cd /home/user/test/team-practice/dev-A
git checkout master
git pull origin master
git merge --no-ff -m "merge feature/pay" origin/feature/pay
git push origin master

# 11. 看历史
git log --graph --pretty=oneline --abbrev-commit --all

跑完这 11 步,你就掌握了 5 人协作的"标准玩法"。


十、📌 关键命令速查表

命令作用
git remote add <name> <url>添加远程仓库
git remote -v查看远程地址
git fetch <remote>抓取远程更新(不合并)
git fetch -p抓取并清理已删除的远程分支
git rebase <branch>变基到目标分支
git rebase --continue解决冲突后继续 rebase
git rebase --abort取消 rebase
git merge --squash <branch>压缩合并
git merge --no-ff <branch>非快进合并
git config rerere.enabled true开启 rerere
git reflog查看所有操作记录
git reset --hard <commit>回到指定 commit
git push --force-with-lease安全强制推送
git commit --amend修改最后一次 commit
git rebase -i HEAD~3交互式 rebase,合并最近 3 个 commit

十一、🤔 几个思考题

学完本文,来试试回答这些问题:

1️⃣ 多人协作时,为什么推荐 rebase 而不是 merge?

答:保持历史线性、可读。

维度mergerebase
历史形态树状分叉线性
merge commit
适合长期 feature 分支短期小功能
安全性任何时候用不能用于已 push 的分支

最佳实践

  • 本地:rebase(保持个人历史干净)
  • 共享分支:merge(不破坏别人历史)

💡 团队可以配置 pull.rebase true,让 pull 自动 rebase。

2️⃣ rebase 改写了历史,团队成员怎么同步?

答:他们需要 git pull --rebase

场景:你在共享分支上 rebase 了,别人本地有"旧"的 commit。

# 队友操作
git fetch origin
git rebase origin/master
# 或
git pull --rebase

这样他们的 commit 会被"重放"到最新 master 上。

⚠️ 如果队友已经基于旧 commit 做了工作,要小心——他们的本地 commit 可能和 rebase 后的 commit 冲突。事先沟通比事后救火重要。

3️⃣ Fork + PR 模式下,upstream 怎么同步?

答:定期 git fetch upstream + merge 到本地 master。

# 1. 配置 upstream(一次性)
git remote add upstream <原仓库URL>

# 2. 同步流程(每次开发前)
git fetch upstream
git checkout master
git merge upstream/master
git push origin master

# 3. 更新你的 feature 分支
git checkout feature/your-feature
git rebase master
git push --force-with-lease origin feature/your-feature

💡 建议把"同步 upstream"加到每天开工的 checklist——避免你的 PR 长期基于"过时版本"。

4️⃣ 团队规范定下来了,怎么强制执行?

答:自动化工具 + Code Review。

工具作用
commitlint检查 commit message 格式
huskygit hooks 工具
ESLint / Prettier检查代码风格
CI/CD自动跑测试、检查
PR 模板强制填写 PR 描述
# 示例:husky + commitlint 强制 commit 规范
# .husky/commit-msg
npx --no-install commitlint --edit "$1"

💡 没有工具的规范 = 没有规范——光靠自觉,3 个月后就会崩。

5️⃣ 团队有人不愿意写 commit message 怎么办?

答:先沟通 + 工具兜底 + 利益绑定。

  1. 沟通:解释 commit message 的价值(debug、回溯、生成 CHANGELOG)
  2. 工具:用 commitlint 强制检查,不规范直接拒绝
  3. 利益:把 commit message 质量纳入绩效考核(虽然听起来残酷,但有效)

千万不要在 review 时长篇大论说教——直接在 PR 里演示 “好的 commit message 长什么样”,比讲道理有用。


写在最后

到这里,《Git 多人协作实战》就告一段落了 🎉

我们从团队角色与流程讲起,深入了 Fork + PR 工作流三种合并策略对比Code Review 流程commit message 规范,最后讲了复杂冲突的解决技巧5 人团队协作实战

学完本篇,你应该能:

  • ✅ 自信地提第一个 PR
  • ✅ 通过 Code Review 提升代码质量
  • ✅ 解决团队协作里的复杂冲突
  • ✅ 理解团队为什么选择特定的工作流

📝 下一篇是整个系列的收官之作——《企业级 Git 开发模型》。我们会从"5 人小作坊"讲到"100 人大厂",把第 1-4 篇的所有知识串成完整的工程实践。Git Flow / GitHub Flow / GitLab Flow 三大经典模型,发版流程规范Code Owner 制度事故应急回滚——真实工业级的 Git 怎么用,全部讲透。

我们下一篇见!


✅ 本节完…

📝 作者:say-fall | 编辑:say-fall | 🌟 原创不易,如果对你有帮助,记得 👍 点赞 + ⭐ 收藏 哦!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值