1. 问题背景:分支混乱与构建雪崩
去年年中,我们团队从10人扩张到25人,迭代节奏从两周一次发版变成每周一次。Git仓库开始出现以下症状:
- 分支命名混乱:有人用
fix/login-bug-v3,有人用feature/add-payment-202310,还有人直接在master上提交 - 合并冲突频繁:平均每次PR有2-3个冲突文件,解决时间占开发总时间15%
- CI构建失败率飙升:40%的提交导致编译失败,原因是代码未通过lint或测试就直接合入主干
- 回滚困难:错误合并导致hotfix需要手动回溯,平均回滚耗时2小时
我作为技术负责人,决定从三个方面重构Git工作流:分支策略、Code Review流程、CI/CD自动化。目标是让每个开发者都能在5分钟内理解“该往哪提交、怎么提、合并后会自动发生什么”。
2. 环境与版本
- Git版本:2.34.1(必须≥2.28,因为后续用到
main默认分支名) - CI/CD平台:GitHub Actions(我们团队使用私有仓库,免费额度足够)
- 代码仓库:单仓库(monorepo),前端+后端分离在
packages/目录 - 依赖管理:pnpm + Node.js 18(构建测试用)
- Code Review工具:GitHub内置PR + 强制Code Owner审批
3. 方案设计:Git Flow + Feature Branch混合模型
我们最终选择了Git Flow的简化版本,结合Feature Branch模式,并去掉了release分支(因为每周发布,用tags代替)。
3.1 分支命名与职责
| 分支类型 | 命名规则 | 来源 | 去向 |
|---|---|---|---|
| 主分支 | main |
- | - |
| 开发分支 | develop |
从main创建 |
合并回main |
| 功能分支 | feature/xxx |
从develop创建 |
合并到develop |
| 修复分支 | hotfix/xxx |
从main创建 |
合并到main和develop |
| 测试分支 | test/xxx |
从develop创建 |
合并到develop |
核心规则:
- 严禁直接向main或develop推送代码,必须通过PR
- main永远对应生产环境稳定版本,只允许hotfix或release tag合并
- develop对应下一个迭代的集成分支,每天至少合入一次
- 功能分支生命周期不超过3天,超过则提醒开发者拆分
3.2 分支流程示例
# 从develop创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-login-refactor
# 开发完成后提交
git add .
git commit -m "feat(user): 重构登录流程,支持OAuth2"
git push origin feature/user-login-refactor
# 创建PR到develop
# 等待CI通过 + 至少1个Code Owner审批
# 合并后删除远程分支
4. 核心实现:Code Review流程与CI/CD配置
4.1 Code Review强制规则
我们在GitHub仓库设置了以下保护规则(通过Settings > Branches > Add rule):
- 要求PR必须至少1个审批:且审批人不能是作者本人
- 要求所有检查通过:包括lint、单元测试、集成测试、构建
- 要求分支是最新的:PR必须基于目标分支的最新commit(防止过时代码冲突)
- 禁止直接推送:
main和develop的push权限只给CI token
实际Review清单(贴在PR模板中):
- 代码风格是否匹配eslint规则?
- 是否有单元测试覆盖新增逻辑?
- 是否修改了数据库Schema(需要额外审批)?
- 是否更新了API文档?
4.2 CI/CD流水线配置(GitHub Actions)
以下是我们真实使用的YAML配置,放在.github/workflows/ci.yml中:
name: CI Pipeline
on:
push:
branches: [ "main", "develop", "feature/**", "hotfix/**" ]
pull_request:
branches: [ "main", "develop" ]
env:
NODE_VERSION: '18.18.2'
PNPM_VERSION: '8.10.0'
jobs:
lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm lint # 输出格式要求:无error,warn数80%
- uses: actions/upload-artifact@v3
if: always()
with:
name: coverage-report
path: coverage/
build:
needs: test
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build # 输出到dist/目录
- uses: actions/upload-artifact@v3
with:
name: build-output
path: dist/
# 仅对main分支执行部署(CD部分)
deploy:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@v3
with:
name: build-output
path: dist/
- run: echo "部署到生产服务器(此处对接你的部署脚本)"
# 实际部署命令示例(保密):
# - run: scp -i ${{ secrets.SSH_KEY }} dist/* user@production:/var/www/app/
关键配置说明:
- 使用--frozen-lockfile确保依赖版本锁定,避免“在我机器上能跑”的问题
- 测试矩阵并行执行unit和integration,总耗时从8分钟降到4分半
- 构建产物作为artifacts上传,便于后续部署或调试
- 部署只针对main分支,且需要所有前置job通过
4.3 踩坑与优化:CI构建失败率从40%降到3%
踩坑1:锁文件不一致
问题:开发者本地pnpm-lock.yaml与CI不一致,导致pnpm install报错
解决:在CI中强制pnpm install --frozen-lockfile,并在pre-commit hook中检查lock文件是否更新
踩坑2:测试超时导致构建失败
问题:集成测试涉及外部API调用,偶尔超时(5分钟限制)
解决:将外部API mock化,测试时间稳定在30秒内;同时设置timeout-minutes: 10避免偶尔卡死
踩坑3:分支保护规则与CI冲突
问题:要求PR必须通过CI,但CI本身需要PR才能触发(死循环)
解决:使用pull_request事件触发CI,同时允许push到develop分支直接触发(用于hotfix紧急场景)
优化后效果:
- CI构建成功率从60%提升到97%(最近30天数据)
- 平均PR从创建到合并时间从4小时缩短到45分钟
- 回滚次数从每月3次降到0次(最近2个月)
5. 效果数据:团队效率提升量化
我们统计了Git工作流重构前后一个季度的数据:
| 指标 | 重构前(季度平均值) | 重构后(季度平均值) | 变化 |
|---|---|---|---|
| 代码冲突率 | 3.2次/周 | 0.3次/周 | -90% |
| CI构建失败率 | 40% | 3% | -92.5% |
| 平均PR合并时间 | 4.1小时 | 0.75小时 | -81.7% |
| 紧急回滚次数 | 3次/月 | 0次/月 | -100% |
| 开发人均有效提交数 | 8.5次/周 | 12.3次/周 | +44.7% |
特别说明:有效提交数增加是因为开发者不用花时间解决冲突和调试CI,可以专注于功能实现。
6. 总结
这次Git工作流重构的核心经验可以总结为三点:
- 分支策略要简单可执行:不要追求完美模型,Git Flow + Feature Branch足够覆盖95%的场景,关键是所有人都遵守规则
- Code Review不是形式,是自动化流程的一环:强制检查、强制审批、强制CI通过,才能保证代码质量
- CI/CD配置要“一次写对,长期维护”:用锁文件、并行测试、分支条件触发,减少人工干预
最后的一个建议:不要一次性推全量改动。我们用了3周逐步切换:第1周只改分支命名规则,第2周引入PR保护,第3周上线CI/CD。每个阶段都让团队适应,效果比强行推行好得多。
如果你也在优化团队Git工作流,可以从“下周一禁止直接push到develop”这个小目标开始。