跳到主要内容
预计阅读 35 分钟

工程化篇 | Git工作流

前言

Git 几乎是每个开发者每天都在用的工具,但很多人对 Git 的使用停留在 add → commit → push 三板斧。真到面试被问到工作流层面的问题,就开始含糊了。

  • 你们团队用的是什么 Git 工作流?为什么选择这个?
  • Git Flow 和 GitHub Flow 有什么区别?
  • Trunk Based Development 是什么?为什么大厂在推它?
  • Commit Message 有什么规范?为什么要规范?
  • Code Review 怎么做才高效?

这些问题考察的不是你”会不会用 Git”,而是你对团队协作和研发流程的理解。一个能清晰阐述工作流选择和原因的候选人,在面试官眼里会加分不少。

本章,我们从三种主流 Git 工作流的对比讲起,再聊分支命名规范、Commit Message 规范、Code Review 流程,以及如何与 CI/CD 集成。


诊断自测

Q1:Git Flow 中有哪些分支?各自的作用是什么?

点击查看答案

Git Flow 定义了五种分支:

  1. main(master):生产环境代码,始终可部署
  2. develop:开发主分支,集成所有已完成的功能
  3. feature/:功能分支,从 develop 分出,开发完合回 develop
  4. release/:发布分支,从 develop 分出,用于发布前的准备和 bug 修复
  5. hotfix/:热修复分支,从 main 分出,修复生产环境紧急 bug

Q2:Conventional Commits 规范中,featfix 分别对应语义化版本(SemVer)的哪个位?

点击查看答案
  • feat(新功能)对应 Minor 版本(如 1.1.0 → 1.2.0)
  • fix(修复)对应 Patch 版本(如 1.1.0 → 1.1.1)
  • 如果 Commit Message 的 footer 中包含 BREAKING CHANGE,则对应 Major 版本(如 1.1.0 → 2.0.0)

这也是 Changesets、semantic-release 等工具自动化版本管理的基础。


一、Git Flow:经典但沉重

1.1 核心思路

Git Flow 由 Vincent Driessen 在 2010 年提出,是最早被广泛采用的 Git 分支策略。

它的核心思路是:用不同类型的分支承载不同阶段的代码

main ────────●────────────────────●──────────
              ↑                    ↑
         hotfix/fix-xxx        merge release

develop ──●──●──●──●──●──●──●──●──●──●───────
           ↑        ↑        ↑
      feature/a  feature/b  release/1.0

1.2 完整工作流

  1. 日常开发在 feature/* 分支上进行
  2. 功能完成后,通过 PR 合并到 develop
  3. 准备发版时,从 develop 创建 release/* 分支
  4. release/* 上做发布前的最后修复
  5. release/* 合并到 main(打 tag)和 develop
  6. 如果生产环境有紧急 bug,从 main 创建 hotfix/*,修复后合并到 maindevelop

1.3 优缺点

优点:

  • 角色明确,适合有明确发版周期的项目
  • 生产代码和开发代码完全隔离

缺点:

  • 分支多、流程重,merge 冲突频繁
  • 不适合持续部署(Continuous Deployment)
  • 在 CI/CD 时代显得过于繁琐

二、GitHub Flow:简单即正义

2.1 核心思路

GitHub Flow 极度简化,只有一个规则:main 分支始终可部署,所有改动通过 PR 合入。

main ─────●─────●─────●─────●─────●─────
           ↑     ↑     ↑     ↑
      feat-a  fix-b  feat-c  feat-d

2.2 完整工作流

  1. main 创建一个描述性命名的分支(如 add-user-auth
  2. 在分支上开发、提交
  3. 开发完成后创建 Pull Request
  4. 团队 Code Review
  5. CI 检查通过后合并到 main
  6. 合并后自动部署

2.3 优缺点

优点:

  • 极简——只有 main 和功能分支
  • 天然适合持续部署
  • 低学习成本

缺点:

  • 不区分”开发中”和”待发布”的代码
  • 不适合需要维护多个版本的场景(如桌面软件、SDK)
  • 对 CI/CD 的依赖很强——如果没有自动化测试保障,直接合入 main 风险大

三、Trunk Based Development:大厂之选

3.1 核心思路

Trunk Based Development(TBD)的核心理念是:所有开发者直接向主干(trunk/main)提交代码,使用短生命周期的分支。

main ──●──●──●──●──●──●──●──●──●──●──●──
        ↑     ↑  ↑           ↑
       PR1   PR2 直接         PR3
                  push

3.2 关键原则

  1. 分支生命周期极短:通常不超过 1-2 天,最好当天创建当天合入
  2. 小步提交:每次提交都是一个小的、可工作的改动
  3. Feature Flags:还没完成的功能用 Feature Flag 隐藏,而不是放在长期分支上
  4. 高频集成:每天至少合入一次到主干

3.3 Feature Flags

Feature Flags(功能开关)是 TBD 的核心配套技术:

// 功能还没开发完,但代码已经在 main 上了
if (featureFlags.isEnabled('new-dashboard')) {
  return <NewDashboard />;
} else {
  return <OldDashboard />;
}

这样你可以把半成品代码合入 main 而不影响线上用户——功能开关关着就行。等功能完成、测试通过,打开开关上线。

3.4 优缺点

优点:

  • 几乎没有 merge 冲突(分支生命周期极短)
  • 代码始终在主干上,团队对代码库的认知一致
  • 天然适合持续集成/持续部署

缺点:

  • 对团队能力要求高:需要熟练的小步提交习惯
  • 需要 Feature Flags 基础设施
  • 需要强大的自动化测试保障

3.5 谁在用 TBD?

Google、Facebook(Meta)、微软、字节跳动等大厂都在推行 TBD。Google 甚至把整个公司的代码放在一个巨大的 Monorepo 里,所有人直接向主干提交。


四、三种工作流对比

维度Git FlowGitHub FlowTrunk Based
复杂度
分支数量极少
分支生命周期极短(<1天)
适合的发布模式定期发版持续部署持续部署
对 CI/CD 的要求极高
对团队的要求
适合场景传统软件、SDKWeb 应用、开源项目大型团队、高频迭代
Feature Flags不需要不需要核心依赖

选型建议:

  • 有明确发版周期的项目 → Git Flow
  • Web 应用、需要快速迭代 → GitHub Flow
  • 大型团队、持续部署、高频迭代 → Trunk Based Development

五、分支命名规范

好的分支命名让团队成员一眼就能看出这个分支在做什么。

5.1 命名规则

<type>/<description>

type: feature, fix, hotfix, refactor, docs, chore, release
description: 用短横线连接的简短描述

5.2 示例

feature/user-authentication
feature/shopping-cart
fix/login-redirect-loop
hotfix/payment-crash
refactor/api-client
docs/api-documentation
chore/upgrade-webpack
release/v2.1.0

5.3 反面例子

❌ my-branch              ← 不知道在做什么
❌ test                   ← 太笼统
❌ wip                    ← 不够描述性
❌ fix-bug                ← 什么 bug?
❌ feature/add-new-feature-for-user-authentication-and-authorization  ← 太长了

六、Commit Message 规范:Conventional Commits

6.1 为什么需要规范?

没有规范的 Commit Message 通常长这样:

fix bug
update
wip
aaa
final fix
final final fix

这样的提交记录毫无价值——你不知道改了什么、为什么改、影响了哪里。

规范的 Commit Message 有三大好处:

  1. 提交历史可读git log 就能看出每次提交做了什么
  2. 自动化:可以自动生成 CHANGELOG、自动确定版本号
  3. 团队协作:新人看提交历史就能了解项目演进过程

6.2 Conventional Commits 格式

<type>(<scope>): <description>

[optional body]

[optional footer]

6.3 type 类型

type说明示例
feat新功能feat(auth): add OAuth2 login
fixBug 修复fix(cart): resolve total calculation error
docs文档修改docs(readme): update installation guide
style格式调整(不影响逻辑)style: fix indentation
refactor重构(不改功能、不修 bug)refactor(api): simplify error handling
perf性能优化perf(list): optimize virtual scroll rendering
test添加/修改测试test(auth): add login unit tests
chore构建/工具变动chore: upgrade webpack to v5
ciCI 配置变动ci: add lint job to pipeline

6.4 完整示例

feat(auth): add email verification flow

- Add email verification page
- Implement verification token generation
- Add expiration check for tokens

Closes #123

6.5 工具支持

  • commitlint:校验 Commit Message 是否符合规范
  • commitizen(cz-cli):交互式命令行工具,引导你填写符合规范的 Message
  • husky:Git Hooks 工具,在 commit 前自动运行 commitlint
# 安装
npm install -D @commitlint/cli @commitlint/config-conventional husky

# 配置 commitlint
echo "module.exports = { extends: ['@commitlint/config-conventional'] }" > commitlint.config.js

# 配置 husky hook
npx husky add .husky/commit-msg 'npx commitlint --edit $1'

七、Code Review 流程

7.1 为什么需要 Code Review?

  • 质量保障:多一双眼睛审查,减少 bug 和设计缺陷
  • 知识共享:团队成员了解彼此的代码,降低”总线因子”
  • 团队规范:通过 Review 统一代码风格和最佳实践
  • 成长:新人通过 Review 学习,老手通过 Review 反思

7.2 好的 PR 长什么样?

  1. :200-400 行代码改动最佳。超过 800 行的 PR 很难认真 Review
  2. 单一职责:一个 PR 只做一件事
  3. 清晰的描述:说清楚改了什么、为什么改、怎么测试
  4. 自测通过:提 PR 前确保 CI 通过

7.3 PR 模板

## What
简要描述这个 PR 做了什么。

## Why
为什么要做这个改动?关联的 Issue/需求是什么?

## How
关键的实现思路或架构决策。

## Test Plan
- [ ] 单元测试通过
- [ ] 手动测试场景 A
- [ ] 手动测试场景 B

## Screenshots
(如果有 UI 变更,贴截图)

7.4 Review 的注意事项

作为 Reviewer:

  • 关注设计和逻辑,不要只挑格式问题(格式问题交给工具)
  • 给出建设性的反馈,而不是”这样不对”
  • 对于不确定的地方,用提问代替断言
  • 及时 Review,不要让 PR 挂着等好几天

作为 Author:

  • 不要在 PR 中包含不相关的改动
  • 主动在关键代码处添加注释说明
  • 收到反馈后及时回复和修改

八、CI/CD 集成

8.1 CI 与 Git 工作流的配合

# GitHub Actions 示例
name: CI
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

  build:
    needs: [lint, test]       # lint 和 test 通过后才 build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build

8.2 分支保护规则

  • main 分支:禁止直接 push,必须通过 PR 合入
  • PR 合入条件:CI 通过 + 至少 1 个 Approve
  • squash merge:把 PR 的多次提交压缩成一个,保持 main 的提交历史干净

常见误区

误区一:“Git Flow 是最佳实践,所有项目都该用”

Git Flow 适合有明确发版周期的项目(如 SDK、桌面应用)。对于 Web 应用这种持续部署的场景,Git Flow 的 develop/release 分支反而是多余的负担。很多团队用了 Git Flow 后发现 develop 和 main 的差异越来越大,合并变得痛苦不堪。选工作流要根据项目类型和团队情况,而不是”别人用什么我就用什么”。

误区二:“Commit Message 规范是形式主义,浪费时间”

短期来看确实多花了几秒钟,但长期收益巨大:自动生成 CHANGELOG、自动化版本管理、提交历史可读可追溯。当你需要回溯三个月前的某个改动时,fix: resolve login redirect loop (#456)fix bug 有用太多了。

误区三:“Code Review 就是挑毛病”

Code Review 的首要目的是质量保障和知识共享,不是找茬。如果你的 Review 只是指出”这个变量名不好”、“这里少个空行”,那确实是在浪费时间——这些应该交给 ESLint 和 Prettier。Review 应该关注架构设计、业务逻辑、边界条件、安全性等机器做不了的事情。

误区四:“Trunk Based Development 就是所有人直接往 main 推代码,不需要 Review”

错。TBD 鼓励频繁地向主干集成,但不意味着跳过 Review。大部分实践 TBD 的团队仍然使用短生命周期的分支 + PR Review,只是分支的生命周期很短(通常不超过一天),而不是像 Git Flow 那样维持数周的长期分支。


小结

本章我们对比了三种主流 Git 工作流(Git Flow、GitHub Flow、Trunk Based Development),梳理了分支命名规范和 Conventional Commits 规范,讲解了 Code Review 的最佳实践,以及如何与 CI/CD 集成。

核心要点

  1. Git Flow:分支多、流程重,适合有明确发版周期的项目
  2. GitHub Flow:极简,main + 功能分支,适合 Web 应用和持续部署
  3. Trunk Based Development:主干开发 + Feature Flags,适合大型团队和高频迭代
  4. Conventional Commits:结构化的提交信息,支持自动化版本管理和 CHANGELOG 生成
  5. Code Review:关注设计和逻辑,而不是格式;PR 要小而聚焦
  6. CI/CD:分支保护 + 自动化检查 + squash merge

本章思维导图

Git 工作流
  • Git Flow
    • 五种分支:main / develop / feature / release / hotfix
    • 适合有明确发版周期的项目
    • 缺点:分支多、合并痛苦
  • GitHub Flow
    • 只有 main + 功能分支
    • 通过 PR 合入,适合持续部署
    • 简单但对 CI/CD 依赖强
  • Trunk Based Development
    • 主干开发,短生命周期分支
    • Feature Flags 隐藏未完成功能
    • 适合大型团队和高频迭代
  • 分支命名规范
    • <type>/<description>
    • feature / fix / hotfix / refactor / docs / chore
  • Commit Message 规范
    • Conventional Commits:<type>(<scope>): <description>
    • 工具:commitlint + husky + commitizen
    • 支持自动化版本管理
  • Code Review
    • PR 要小(200-400 行)、单一职责
    • 关注设计和逻辑,格式交给工具
    • 及时 Review,建设性反馈
  • CI/CD 集成
    • PR 触发 CI(lint + test + build)
    • 分支保护规则
    • squash merge 保持历史干净

练习挑战

第一题 ⭐(基础):Commit Message 改写

请把下面不规范的 Commit Message 改写成符合 Conventional Commits 规范的格式:

  1. fixed login bug
  2. add new feature for user profile page
  3. update README
点击查看答案与解析
  1. fix(auth): resolve login redirect loop —— 使用 fix 类型,加上 scope 说明模块,description 描述具体修了什么
  2. feat(profile): add user profile page —— 使用 feat 类型,简洁描述新功能
  3. docs(readme): update installation guide —— 使用 docs 类型,说明更新了什么内容

改写要点:

  • 使用正确的 type
  • description 用英文祈使句(动词原形开头)
  • 尽可能加上 scope
  • 简洁但有信息量

第二题 ⭐⭐(进阶):工作流选型

你们团队有 5 个开发者,开发一个 ToB SaaS 产品。目前使用 Git Flow,但经常出现以下问题:

  • develop 分支上积累了大量未发布的功能,和 main 的差异越来越大
  • release 分支经常要处理很多合并冲突
  • hotfix 合入 develop 时经常忘记

请分析问题原因,并提出改进方案。

点击查看答案与解析

问题分析:

这些问题是 Git Flow 的典型痛点:

  1. develop 积累过多未发布功能 → 说明发版周期太长,功能在 develop 上”排队等候”
  2. release 分支合并冲突多 → develop 和 main 差异太大的直接后果
  3. hotfix 忘记合入 develop → 分支太多,流程容易遗漏

改进方案:

对于 5 人团队的 SaaS 产品,建议迁移到 GitHub Flow

  1. 去掉 develop 和 release 分支,只保留 main + 功能分支
  2. 每个功能完成后直接通过 PR 合入 main
  3. main 分支始终可部署,合入后自动部署到 staging 环境
  4. 手动触发从 staging 到 production 的部署(或根据信心程度自动部署)
  5. 配合自动化测试保障 main 的质量

如果某些功能需要较长时间开发,使用 Feature Flags 而不是长期分支:

if (featureFlags.isEnabled('new-billing')) {
  return <NewBilling />;
}
return <OldBilling />;

这样功能代码可以频繁合入 main(持续集成),但用户看不到(通过 Flag 控制)。等功能完成测试后,打开 Flag 即可上线。

第三题 ⭐⭐⭐(综合):设计 Code Review + CI 流程

请为一个中型前端项目设计完整的 PR → Review → CI → 合并流程,包括:

  1. PR 创建时需要填写哪些信息?
  2. CI 应该跑哪些检查?
  3. Review 的标准和规则是什么?
  4. 合并策略是什么?
点击查看答案与解析

一、PR 创建规范

使用 PR 模板(.github/pull_request_template.md):

## Summary
一句话说明这个 PR 做了什么。

## Changes
- 改动点 1
- 改动点 2

## Related Issues
Closes #issue_number

## Test Plan
- [ ] 单元测试
- [ ] 本地手动测试
- [ ] 特殊场景测试(边界条件、错误状态等)

## Screenshots
(有 UI 改动时必填)

二、CI 检查项

jobs:
  # 1. 代码质量
  lint:
    steps:
      - run: pnpm lint           # ESLint
      - run: pnpm format:check   # Prettier 格式检查
      - run: pnpm typecheck      # TypeScript 类型检查

  # 2. 测试
  test:
    steps:
      - run: pnpm test -- --coverage
      - uses: codecov/codecov-action  # 上传覆盖率报告

  # 3. 构建
  build:
    needs: [lint, test]
    steps:
      - run: pnpm build

  # 4. Bundle Size 检查
  bundle-size:
    steps:
      - uses: andresz1/size-limit-action  # 检查构建产物大小是否超标

  # 5. Commit Message 检查
  commitlint:
    steps:
      - run: npx commitlint --from ${{ github.event.pull_request.base.sha }}

三、Review 规则

  • 至少 1 个 Approve 才能合入(关键模块要求 2 个)
  • 配置 CODEOWNERS:特定目录的修改必须由对应的负责人 Review
  • Review 关注点优先级:架构设计 > 业务逻辑 > 边界处理 > 性能 > 命名/风格
  • Review SLA:24 小时内给出首次反馈

四、合并策略

  • 使用 Squash Merge:把 PR 中的多次提交压缩成一个
  • Squash Commit Message 使用 PR 标题(符合 Conventional Commits 格式)
  • 合并后自动删除功能分支
  • 合并后触发 staging 环境自动部署

自我检测

  • 能描述 Git Flow、GitHub Flow、Trunk Based Development 三种工作流的核心差异
  • 能根据项目类型和团队情况给出工作流选型建议
  • 能说出 Trunk Based Development 中 Feature Flags 的作用
  • 能写出符合 Conventional Commits 规范的 Commit Message
  • 能说出为什么 Commit Message 规范对自动化版本管理很重要
  • 能描述一个好的 PR 应该具备哪些特征
  • 能设计一个完整的 PR → CI → Review → 合并流程
  • 能配置 commitlint + husky 来自动化 Commit Message 校验

购买课程解锁全部内容

大厂前端面试通关:71 篇构建完整知识体系

¥89.90