编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • 质量保障

  • 产品思考

  • 软实力

  • 开发流程

  • Git应用

    • README
    • 版本控制的诞生:从一场灾难说起
    • 单人工作流:在 Git 的时光机里自由穿梭
    • 分支:Git 的灵魂——像开平行宇宙一样开发
    • 远程协作:把你的代码推到全世界
    • Git特种作战:stash、cherry-pick、bisect三件套
    • 团队工作流实战:从一个人能打到一队人能战
      • 一、团队失控
      • 二、Git Flow
        • 2.1 五种分支,各司其职
        • 2.2 完整的 Git Flow 模拟
        • 2.3 Git Flow 的优势与劣势
      • 三、GitHub流
        • 3.1 只有一条长期分支 + 临时 feature 分支
        • 3.2 GitHub Flow 实战
        • 3.3 选 Git Flow 还是 GitHub Flow?
      • 四、保护分支
        • 4.1 在 GitHub 上配置
        • 4.2 配置后的效果
        • 4.3 保护分支的典型配置组合
      • 五、提交规范
        • 5.1 为什么消息格式很重要?
        • 5.2 Conventional Commits 规范
        • 5.3 Commit 规范速查
        • 5.4 用交互式 rebase 修正之前的 message
      • 六、忽略文件
        • 6.1 基本用法
        • 6.2 全局 .gitignore
        • 6.3 如果已经提交了不该提交的文件
      • 七、CI/CD 集成
        • 7.1 概念
        • 7.2 GitHub Actions 示例
      • 八、综合实战
        • 场景设定
        • 实战开始
        • 🎯 Sprint 时间线
      • 九、本章回顾
        • 📎 本章涉及的命令速查
    • Git故障排除:遇到报错不再慌的急诊手册
    • Git 场景速查地图:遇到问题对号入座
    • 常见操作实践:从理论到实战的最后一步
  • 技术模版

  • 技术规范

  • markdown

  • mermaid

  • license

  • 博客部署

  • 技术招聘

  • 测试经验

  • 技术
  • Git应用
杨充
2025-06-06
目录

团队工作流实战:从一个人能打到一队人能战

# 第6章 · 团队工作流

# 一、团队失控

前五章,小李都是一个人或两三个人协作。虽然偶尔有点混乱,但靠沟通就能解决——喊一嗓子「别 push,我在改这个文件」,大家就停下来。

三个月后,公司拿到了融资,团队从 3 人扩到 15 人。噩梦开始了:

周一早上 9 点,小李打开 Slack,看到 47 条未读消息:

小王:「谁 push 了 broken code 到 master?线上挂了!」 小张:「我昨天推的,但我本地是好的啊。」 小王:「你是不是没 pull 最新代码就 push 了?」 小张:「我 pull 了啊……可能是李哥的吧?」 小李:「我改的是 coupons.js,跟支付无关。」

没人知道线上挂的原因,也没人知道谁应该修。 更糟的是:

  • 🚫 有人直接往 master 推未经审查的代码,线上两次回滚
  • 🚫 有人在同一个 feature 分支上同时做三个功能,想拆都拆不开
  • 🚫 没有发布流程——每次上线靠「感觉差不多了就推」
  • 🚫 Commit message 惨不忍睹:fix、update、改了一下、asdf

问题本质:不是团队缺 Git 技能,而是缺一套每个人都遵守的游戏规则。

这就是团队工作流要解决的问题:不是让你更会用 Git,而是让 15 个人像一个人一样协同。


# 二、Git Flow

# 2.1 五种分支,各司其职

Git Flow 是 Vincent Driessen 在 2010 年提出的,虽然现在被认为「重量级」,但它把「分支职责」这个概念讲得最透彻。

                    ┌─ feature/支付 ─┐
                   ╱                  ╲
──○──○────○──────○────────────────────○────────────○──  main
       ╲        ╱ ╲                  ╱ ╲          ╱
        ○──○──○───○──○──○────○────○───○──○──○──○──  develop
                              ╲   ╱          ╲   ╱
                          release/1.0    hotfix/紧急
1
2
3
4
5
6
7
分支 生命周期 来源 合并到 命名
main 永久 - - main 或 master
develop 永久 main - develop
feature 临时 develop develop feature/xxx
release 临时 develop main + develop release/v1.2.0
hotfix 临时 main main + develop hotfix/xxx

核心规则:

  • main 只存生产代码——任何时候从 main 拉出来的代码都能直接部署。
  • develop 是集成分支——所有 feature 先合到 develop,测试通过后才合到 main。
  • feature 从 develop 出,回 develop——一个 feature 一个分支,做完就删。
  • release 是发布前的最后一道关——修 bug、改版本号、打 tag,不改新功能。
  • hotfix 从 main 出,同时回合 main 和 develop——确保修复在主线和开发线都不丢失。

# 2.2 完整的 Git Flow 模拟

mkdir gitflow-lab && cd gitflow-lab && git init

# ==================== Step 1:建立主分支结构 ====================
echo "const app = 'Shop v0.0.1';" > app.js
git add . && git commit -m "init: 项目初始化"

# 从 main 分出 develop
git branch develop

# main 打初始标签
git tag v0.0.1


# ==================== Step 2:两人并行开发两个 feature ====================

# 小李:开发商品搜索
git switch develop
git switch -c feature/商品搜索

echo '
function searchProducts(keyword) {
  return db.query("SELECT * FROM products WHERE name LIKE ?", [`%${keyword}%`]);
}
' > search.js

git add . && git commit -m "feat: 商品搜索功能"

# 小张:开发购物车(从 develop 开出另一个分支)
git switch develop
git switch -c feature/购物车

echo '
const cart = [];
function addToCart(id) { cart.push(id); }
function getCartTotal() { return cart.length; }
' > cart.js

git add . && git commit -m "feat: 购物车添加功能"

echo '
function removeFromCart(id) {
  const idx = cart.indexOf(id);
  if (idx > -1) cart.splice(idx, 1);
}
' >> cart.js
git add . && git commit -m "feat: 购物车移除功能"


# ==================== Step 3:feature 合并到 develop ====================

# 小李先合并搜索功能
git switch develop
git merge --no-ff feature/商品搜索 -m "merge: 合并商品搜索功能"
git branch -d feature/商品搜索

# 小张接着合并购物车功能
git merge --no-ff feature/购物车 -m "merge: 合并购物车功能"
git branch -d feature/购物车

git log --oneline --graph
# 输出:
# *   merge: 合并购物车功能
# |\
# | * feat: 购物车移除功能
# | * feat: 购物车添加功能
# |/
# *   merge: 合并商品搜索功能
# |\
# | * feat: 商品搜索功能
# |/
# * init: 项目初始化


# ==================== Step 4:准备发布——创建 release 分支 ====================
git switch -c release/v1.0.0 develop

# 在 release 上只做发布准备:修小 bug、改版本号
echo "const APP_VERSION = '1.0.0';" >> app.js
git add . && git commit -m "chore: 更新版本号到 1.0.0"

# 发现一个 display bug——修复
echo "// 修复:移动端搜索框宽度问题" >> search.js
git add . && git commit -m "fix: 搜索框移动端适配"

# 测试通过 → 发布!

# 合并到 main
git switch main
git merge --no-ff release/v1.0.0 -m "release: v1.0.0 正式发布"

# 打发布标签
git tag -a v1.0.0 -m "v1.0.0 正式版:商品搜索 + 购物车"

# 别忘了:release 分支上的修复也要同步回 develop!
git switch develop
git merge --no-ff release/v1.0.0 -m "merge: 同步 release v1.0.0 的修复"

# 清理 release 分支
git branch -d release/v1.0.0


# ==================== Step 5:线上出 bug → hotfix ====================
# v1.0.0 发布后,线上发现购物车的移除功能在空购物车时报错

# hotfix 从 main 开出
git switch -c hotfix/空购物车崩溃 main

# 修复
cat > cart.js << 'EOF'
const cart = [];
function addToCart(id) { cart.push(id); }
function getCartTotal() { return cart.length; }
function removeFromCart(id) {
  const idx = cart.indexOf(id);
  if (idx > -1) cart.splice(idx, 1);
}
// 修复:空购物车返回空数组而非报错
function getCartItems() {
  return [...cart];
}
EOF

git add . && git commit -m "hotfix: 修复空购物车调用 remove 崩溃"

# 修改版本号
echo "const APP_VERSION = '1.0.1';" > app.js
git add . && git commit -m "chore: 版本号 1.0.1"

# 合并到 main
git switch main
git merge --no-ff hotfix/空购物车崩溃 -m "merge: hotfix 空购物车崩溃"
git tag -a v1.0.1 -m "v1.0.1 热修复:空购物车崩溃"

# 🚨 关键!合并到 develop!否则 develop 上还会有这个 bug!
git switch develop
git merge --no-ff hotfix/空购物车崩溃 -m "merge: 同步 hotfix 空购物车修复"

# 清理
git branch -d hotfix/空购物车崩溃
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

# 2.3 Git Flow 的优势与劣势

优势:

  • ✅ 结构清晰,五种分支各司其职,新人一看就懂
  • ✅ 严格的发布流程,不会发生「忘记修了什么就上线了」
  • ✅ main 永远稳定,任何时候都能部署

劣势:

  • ❌ 重型——小团队三四个人的项目,走完整流程太慢
  • ❌ 分支多——同时维护 feature / release / hotfix 多条线,容易忘同步
  • ❌ 不适合持续部署——如果你的团队一天发 10 次版,等 release 分支太慢了

# 三、GitHub流

# 3.1 只有一条长期分支 + 临时 feature 分支

   main ──○────────○─────────○──────────○────
           ╲        ╲         ╲          ╲
            ○──○──○  ○──○  ○──○──○  ○──○   ← feature 分支
1
2
3

规则极其简单:

  1. main 永远是可部署状态。
  2. 任何新东西,从 main 开出 feature 分支。
  3. feature 分支开发完,提 Pull Request。
  4. PR 审查通过 → 合并到 main → 立即部署。
  5. 部署后发现 bug → 从 main 开新的分支修复(同步骤 2~4)。

没有 develop,没有 release,只有 main + 一堆短暂的 feature 分支。

# 3.2 GitHub Flow 实战

# 和 Git Flow 的区别:没有 develop,直接从 main 出分支
git switch main
git switch -c feature/商品推荐

# 开发...
echo "function recommend() { /* 推荐算法 */ }" > recommend.js
git add . && git commit -m "feat: 商品推荐功能"

# push + 提 PR
git push -u origin feature/商品推荐

# 去 GitHub 创建 PR:base main ← compare feature/商品推荐
# 审查 → 通过 → Merge → 立即部署到生产环境

# 清理
git switch main
git pull origin main
git branch -d feature/商品推荐
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3.3 选 Git Flow 还是 GitHub Flow?

维度 Git Flow GitHub Flow
长期分支 main + develop 只有 main
发布节奏 定期发布(周/月) 持续部署(每天多次)
适用场景 有固定发版周期的项目(App、硬件) Web 服务、SaaS
团队规模 中大型(10+ 人) 不限
学习曲线 陡 平
回滚难度 低(有 release 分支做缓冲) 中等(main 即生产)

💡 建议:如果你的项目有「版本号」这个概念且用户不能随时更新(如手机 App),用 Git Flow。如果你的项目是 Web 服务、用户访问时自动拿到最新版,用 GitHub Flow。


# 四、保护分支

无论用哪种 Flow,有一个铁律必须强制执行:禁止任何人直接 push 到 main。

# 4.1 在 GitHub 上配置

在仓库 → Settings → Branches → Add branch protection rule:

Branch name pattern: main(或 master)

☑ Require a pull request before merging
  ☑ Require approvals (至少 1 人通过)
☑ Require status checks to pass before merging
☑ Require branches to be up to date before merging
☑ Include administrators  (连管理员也不能绕过)
1
2
3
4
5
6
7

# 4.2 配置后的效果

# 当有人试图直接 push main:
git push origin main

# 输出:
# remote: error: GH006: Protected branch update failed for refs/heads/main.
# remote: error: At least 1 approving review is required.
# ! [remote rejected] main -> main (protected branch hook declined)
1
2
3
4
5
6
7

直接 push 被拒绝! 只能通过 Pull Request 合入。

# 4.3 保护分支的典型配置组合

# 最小保护(小团队推荐):
- 需要 PR 才能合并
- 至少 1 人审查通过

# 标准保护(中大型团队):
- 需要 PR 才能合并
- 至少 2 人审查通过
- CI 测试必须通过
- 分支必须是最新的(不能和 main 有冲突)
- 禁止 force push

# 严格保护(金融/医疗):
- 以上全部
- 要求的审查者必须来自 CODEOWNERS 文件
- 提交必须签名验证
- 合并前必须解决所有评论
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 五、提交规范

# 5.1 为什么消息格式很重要?

看两组 commit log:

# 组 A(混乱)
fix
update
改了一下
asdf
修 bug
feat: 具体的功能
真的修好了
1
2
3
4
5
6
7
8
# 组 B(规范)
feat: 添加商品搜索功能
fix: 修复购物车空数组崩溃
docs: 更新 API 文档
refactor: 重构支付模块回调逻辑
chore: 升级依赖到 v2.0
test: 添加搜索功能单元测试
1
2
3
4
5
6
7

组 B 的好处:

  • 📜 git log --oneline 就是你的 CHANGELOG
  • 🤖 可以自动生成版本号(feat → 次版本号 +1,fix → 修订号 +1)
  • 👀 Code Review 时,审查者一秒知道你的意图
  • 🔍 git log --grep="fix:" 快速过滤所有修复

# 5.2 Conventional Commits 规范

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

# type(必填):
feat      → 新功能
fix       → 修复 bug
docs      → 文档
style     → 格式(不影响逻辑)
refactor  → 重构(不增功能也不修 bug)
perf      → 性能优化
test      → 测试
chore     → 构建/依赖/工具
ci        → CI 配置
build     → 构建系统

# scope(可选):
feat(cart): 添加购物车优惠计算
fix(auth): 修复 token 过期未刷新
docs(api): 更新商品接口文档

# subject(必填):
- 用祈使句("添加" 而不是 "添加了")
- 首字母小写
- 结尾不加句号
- 不超过 72 字符

# body(可选):
为什么这么改、怎么改的、有什么副作用

# footer(可选):
BREAKING CHANGE: 不兼容变更说明
Closes #123
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 5.3 Commit 规范速查

你的改动 用这个 type 例子
加了登录功能 feat feat(auth): 添加用户登录接口
修了空指针崩溃 fix fix(cart): 修复空购物车 remove 崩溃
改了 README docs docs: 更新安装说明
重命名变量 refactor refactor(user): 重命名 getUser 为 fetchUser
删了无用 import style style: 移除未使用的 import
加了单元测试 test test(cart): 添加购物车计算测试
升级 React 版本 chore chore(deps): 升级 react 到 18.2

# 5.4 用交互式 rebase 修正之前的 message

# 最近 3 个 commit 的 message 写得不规范
git rebase -i HEAD~3

# 把 pick 改成 reword:
# reword aaa111 fix
# reword bbb222 update
# reword ccc333 改了一下

# Git 依次弹出编辑器让你改 message:
# fix       → fix(cart): 修复空购物车崩溃
# update    → feat(cart): 添加优惠计算
# 改了一下   → refactor(auth): 简化 token 验证逻辑
1
2
3
4
5
6
7
8
9
10
11
12

# 六、忽略文件

# 6.1 基本用法

# .gitignore 文件
node_modules/         # 忽略整个目录
dist/                 # 构建产物
.env                  # 环境变量(含密钥!)
*.log                 # 所有日志文件
.DS_Store             # macOS 系统文件
*.swp                 # vim 临时文件
.vscode/              # 编辑器配置(看团队约定)

# 例外:虽然忽略 .env,但要保留模板
!.env.example         # 感叹号 = 不忽略
1
2
3
4
5
6
7
8
9
10
11

# 6.2 全局 .gitignore

# 对于所有项目的通用忽略(如 .DS_Store):
git config --global core.excludesfile ~/.gitignore_global

# 编辑 ~/.gitignore_global
echo ".DS_Store" >> ~/.gitignore_global
echo "*.swp" >> ~/.gitignore_global
1
2
3
4
5
6

# 6.3 如果已经提交了不该提交的文件

# 第一步:从 Git 跟踪中移除(但保留本地文件)
git rm --cached node_modules/ -r

# 第二步:把 node_modules/ 加入 .gitignore
echo "node_modules/" >> .gitignore

# 第三步:提交
git add .gitignore
git commit -m "chore: 从仓库移除 node_modules,加入 gitignore"

# 第四步:push
git push
1
2
3
4
5
6
7
8
9
10
11
12

# 七、CI/CD 集成

# 7.1 概念

  git push ──→ CI 自动运行 ──→ 测试通过? ──→ 自动部署
                    │                        │
                    └── 测试失败? ← 通知开发者修复
1
2
3

CI(持续集成):每次 push 自动跑测试、lint、构建。 CD(持续部署):测试通过后自动部署到生产环境。

# 7.2 GitHub Actions 示例

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npm ci
      - run: npm test
      - run: npm run lint
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

有了这个文件,每次 push 或提 PR,GitHub 自动跑测试。测试不通过 → PR 不能合并(配合保护分支的 Require status checks)。


# 八、综合实战

# 场景设定

团队要发布电商平台 v1.1.0,这个版本包含:

  • 小李:商品收藏功能
  • 小王:订单历史查询
  • 期间:一个线上紧急 bug(图片加载失败)

采用 GitHub Flow(因为这是个 Web 项目,持续部署)。

# 实战开始

mkdir team-workflow && cd team-workflow && git init

# 初始化项目
echo 'const app = { name: "Shop", version: "1.0.0" };' > app.js
echo 'node_modules/' > .gitignore
git add . && git commit -m "init: 电商平台 v1.0.0"
git tag -a v1.0.0 -m "v1.0.0 初始版本"


# ==================== Sprint 1:并行开发两个 feature ====================

# --- 小李:商品收藏 ---
git switch -c feature/商品收藏

echo '
const favorites = [];
function addFavorite(productId) {
  if (!favorites.includes(productId)) {
    favorites.push(productId);
  }
}
function removeFavorite(productId) {
  const idx = favorites.indexOf(productId);
  if (idx > -1) favorites.splice(idx, 1);
}
' > favorites.js

git add . && git commit -m "feat(favorites): 添加商品收藏功能"

echo '
function isFavorite(productId) {
  return favorites.includes(productId);
}
' >> favorites.js
git add . && git commit -m "feat(favorites): 添加收藏状态查询"

# 整理 commit
git rebase -i HEAD~2
# squash 成一个:feat(favorites): 实现完整商品收藏功能

git push -u origin feature/商品收藏
# 去 GitHub 创建 PR


# --- 小王:订单历史 ---
git switch main
git switch -c feature/订单历史

echo '
const orders = [];
function getOrderHistory(userId) {
  return orders.filter(o => o.userId === userId);
}
function getOrderDetail(orderId) {
  return orders.find(o => o.id === orderId);
}
' > orders.js

git add . && git commit -m "feat(orders): 添加订单历史查询"

echo '
function getOrdersByDate(userId, startDate, endDate) {
  return orders.filter(o =>
    o.userId === userId &&
    o.date >= startDate &&
    o.date <= endDate
  );
}
' >> orders.js
git add . && git commit -m "feat(orders): 添加按日期范围查询"

git rebase -i HEAD~2
# squash → feat(orders): 实现完整订单历史查询功能

git push -u origin feature/订单历史
# 去 GitHub 创建 PR


# ==================== 审查 & 合并 ====================

# Code Review 流程:
# 1. 小李审查小王的 PR → 提了一个问题:"缓存策略是什么?"
# 2. 小王回复:"第一版不做缓存,下个 Sprint 加"→ 审查通过 → Merge
# 3. 小王审查小李的 PR → 建议:"addFavorite 应该返回布尔值表示是否成功"
# 4. 小李修改:
git switch feature/商品收藏
sed -i '' 's/favorites.push(productId);/favorites.push(productId); return true;/' favorites.js
git add . && git commit -m "fix(favorites): 收藏操作返回布尔结果"
git push origin feature/商品收藏
# PR 自动更新 → 审查通过 → Merge

# 拉最新 master
git switch main
git pull origin main


# ==================== 🚨 紧急:线上图片加载失败 ====================
# 用户反馈:商品详情页图片全部不显示
# 排查:CDN 链接过期

git switch -c hotfix/图片CDN main

echo 'const IMAGE_CDN = "https://new-cdn.example.com";' > config.js
git add . && git commit -m "hotfix(cdn): 修复图片 CDN 链接过期"

# 提 PR,紧急审查,2 分钟通过 → Merge 到 main
# 自动部署 → 线上恢复 🎉


# ==================== 发布 v1.1.0 ====================
git switch main
git pull origin main

# 更新版本号
echo 'const app = { name: "Shop", version: "1.1.0" };' > app.js
git add . && git commit -m "chore(release): 准备发布 v1.1.0"

git tag -a v1.1.0 -m "v1.1.0: 商品收藏 + 订单历史 + 图片 CDN 修复"
git push origin main --tags

# 🎉 v1.1.0 发布完成!


# ==================== Sprint 回顾 ====================
git log --oneline --graph main

# 输出:
# * chore(release): 准备发布 v1.1.0
# * Merge PR #3 (hotfix/图片CDN)
# * Merge PR #2 (feature/订单历史)
# * Merge PR #1 (feature/商品收藏)
# * init: 电商平台 v1.0.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

# 🎯 Sprint 时间线

  周一                周三                   周五
────┼───────────────────┼─────────────────────┼────→
    │                   │                     │
  Sprint 开始          🚨 线上 CDN bug       v1.1.0 发布
  小李开收藏分支       紧急 hotfix 修复       两个 feature 合并
  小王开订单分支       15分钟搞定            打 tag 上线
                               │
                               └── hotfix 修复直接部署,不阻塞 feature 开发
1
2
3
4
5
6
7
8

# 九、本章回顾

我学会了什么 一句话总结
Git Flow 五种分支:main / develop / feature / release / hotfix,适合定期发版
GitHub Flow 只有 main + feature 分支,PR 合并即部署
保护分支 禁止直接 push main,必须 PR + 审查 + CI 通过
Conventional Commits feat: / fix: / docs: 等规范前缀,让 log 变成 changelog
.gitignore 排除 node_modules、.env、日志等不该进仓库的文件
CI/CD 每次 push 自动跑测试,通过后自动部署
Code Review 到具体代码行提建议,修改后 PR 自动更新

🎯 团队工作流的核心不是技术,是纪律:

  1. 永远不直接 push main——无论多小的改动,一律走 PR。
  2. Commit 用规范前缀——feat: / fix: / docs:,让历史自己说话。
  3. Hotfix 的修复必须同步到所有活跃分支——修了 main 别忘了 develop。
  4. 合并完就删分支——别让 git branch 输出滚三页。

🏃 下一章预告:现在你已经能在团队中作战了。但 Git 不是完美的——有时候你会遇到各种报错、误操作、灾难现场。下一章是故障排除 & 常见问题:detached HEAD 是什么鬼、merge conflict 的五种场景、误删分支怎么恢复、大文件误提交怎么清理历史。从「会用」到「能排错」。


# 📎 本章涉及的命令速查

# === Git Flow 完整流程 ===
git branch develop                            # 从 main 创建 develop
git switch -c feature/xxx develop             # 从 develop 开 feature
git merge --no-ff feature/xxx                 # 合并 feature(保留历史)
git switch -c release/v1.0.0 develop          # 从 develop 开 release
git merge --no-ff release/v1.0.0              # release 合并到 main + develop
git tag -a v1.0.0 -m "message"                # 打发布标签
git switch -c hotfix/xxx main                 # 从 main 开 hotfix
# hotfix 必须同时合并到 main 和 develop!

# === GitHub Flow ===
git switch -c feature/xxx main                # 从 main 开 feature
git push -u origin feature/xxx                # 推送
# 去 GitHub 创建 PR → 审查 → Merge → 部署
git branch -d feature/xxx                     # 清理本地

# === 保护分支(在 GitHub 网页端配置) ===
# Settings → Branches → Add rule
# Branch name pattern: main
# ☑ Require a pull request before merging
# ☑ Require approvals
# ☑ Require status checks to pass

# === Commit 规范 ===
# feat(scope): 描述       → 新功能
# fix(scope): 描述        → 修复 bug
# docs(scope): 描述       → 文档
# refactor(scope): 描述   → 重构
# chore(scope): 描述      → 构建/依赖
# test(scope): 描述       → 测试
# 修改历史 message:git rebase -i HEAD~N → reword

# === .gitignore ===
# node_modules/   → 依赖目录
# .env            → 环境变量(密钥!)
# dist/ build/    → 构建产物
# *.log           → 日志文件
# .DS_Store       → macOS 系统文件
# !.env.example   → 例外(不忽略模板)

# === 已推送的大文件清理 ===
git rm --cached <file>                      # 从跟踪中移除
git commit -m "chore: 移除大文件"
git push
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#Git
上次更新: 2026/06/07, 10:26:12
Git特种作战:stash、cherry-pick、bisect三件套
Git故障排除:遇到报错不再慌的急诊手册

← Git特种作战:stash、cherry-pick、bisect三件套 Git故障排除:遇到报错不再慌的急诊手册→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式