“Git 是每个工程师每天都在用的工具,但大多数团队的 Git 工作流一团糟。分支策略不对,合并冲突能毁掉一个 Sprint。“
前言
在汇丰银行,从 SVN 迁移到 Git 已经是过去的事了,但团队协作的混乱仍然普遍存在。分支命名混乱、Commit 信息没有规范、Code Review 流于形式——这些问题在小型团队里不明显,但在 50+ 人同时开发同一个系统的团队里,是灾难性的。
1. 两种主流分支策略对比
GitFlow(适合:发布周期固定的传统软件)
Trunk-Based Development(适合:持续交付的敏捷团队)
1.1 GitFlow:经典但沉重
长期分支:
main/master ──────┬───────────────────→ 发布历史
│ ← release/* 从 main 切出
develop ──┬─→─┬─────────────────→ 开发主分支
短期分支(从 develop 切出):
feature/PROJ-123-user-auth ← 功能分支
bugfix/PROJ-456-login-crash ← 修复分支
hotfix/PROJ-789-security-fix ← 紧急热修复(从 main 切出)
发布节奏:
develop → 合并 → release/v1.2 → 测试 → 发布 → 合并回 main + develop
每次发布周期 2-4 周
# GitFlow 命令序列
# 1. 从 develop 创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/PROJ-123-payment-reconciliation
# 2. 开发完成后,提交 PR 合并回 develop
git push origin feature/PROJ-123-payment-reconciliation
# → 创建 Pull Request → Code Review → 合并
# 3. 发布:从 develop 创建 release 分支
git checkout develop
git checkout -b release/v1.2.0
# → QA 测试 → 修复 → 测试通过
# 4. 发布完成:合并回 main 和 develop
git checkout main
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release v1.2.0"
git push origin main --tags
git push origin develop
# 5. 热修复:从 main 切出 hotfix
git checkout -b hotfix/PROJ-789-security-fix main
# → 修复 → 合并回 main + develop
1.2 Trunk-Based Development:轻量且持续
策略:所有开发者在短生命周期(<1 天)的特性分支上工作,
频繁合并回 main(trunk),保持主干始终可发布。
长期分支:main(唯一的真相来源)
短期分支:
feat/PROJ-123-add-webhook ← 生命周期 < 1 天
fix/PROJ-456-null-pointer-exception ← 生命周期 < 1 天
refactor/PROJ-789-simplify-validator ← 生命周期 < 1 天
发布方式:
main → 合并 → 直接发布(持续交付)
或者:发布分支从 main 切出(仅发布用,不合并回 main)
release/2026-Q1 ← 从 main 切出 → 冻结 → 发布 → 废弃
# TBD 命令序列
# 1. 从 main 切出短生命特性分支(强烈建议 < 1 天)
git checkout main
git pull origin main
git checkout -b feat/PROJ-123-payment-webhook
# 编写代码...
git push origin feat/PROJ-123-payment-webhook
# 2. 创建 PR,合并前确保 CI 全部通过
# 重要:PR 合并后立即删除分支,避免分支爆炸
# 3. 特性开关控制未完成功能
# 代码合并到 main,但通过 feature flag 控制上线
if (featureToggle.isEnabled("new-payment-flow")) {
return newPaymentFlow();
}
return oldPaymentFlow();
1.3 银行团队选哪个?
| 因素 | GitFlow | Trunk-Based |
|---|---|---|
| 发布节奏 | 定期发布(2-4 周) | 持续交付(每日可发布) |
| 团队规模 | 中小型(< 20 人) | 大型(20+ 人) |
| 合规要求 | 变更需审批 → 适合 | ⚠️ 需额外审批流程 |
| Hotfix 频率 | 高 → 适合 | ⚠️ 需要机制支持 |
| CI/CD 成熟度 | 中等 | 高 |
汇丰的做法:核心银行系统通常用改良版 GitFlow(长发布周期需要 release 分支隔离),内部工具和微服务用 TBD(快速迭代)。
2. 分支命名规范
# ✅ 推荐命名:<类型>/<项目>-<工单号>-<简短描述>
# 功能分支
git checkout -b feat/PROJ-123-add-hk-payment-gateway
git checkout -b feat/CMB-456-invoice-reconciliation
# 修复分支
git checkout -b fix/PROJ-789-null-pointer-in-payment
git checkout -b fix/HW-101-timeout-retry-logic
# 重构分支
git checkout -b refactor/PROJ-321-simplify-validator
# 发布分支
git checkout -b release/v2.1.0
git checkout -b release/2026-Q1
# 热修复分支
git checkout -b hotfix/PROJ-999-security-patch-cve-2026
# ❌ 避免命名:
feature/user-login # 没有工单号,无法追踪
bug-fix-123 # 格式混乱
dev # 和 main 重复
john-feature # 包含人名,不规范
3. Commit 规范:Commitizen + Conventional Commits
3.1 Conventional Commits 标准
<type>(<scope>): <subject>
[body]
[footer]
# 示例
feat(payment): add SWIFT gpi transaction tracking
Implemented UETR tracking for SWIFT gpi payments.
Added gpi_status webhook handler.
Updated transaction query to support gpi_uetr field.
Closes: PROJ-123
Reviewed-by: @colleague
3.2 Type 类型定义
| Type | 用途 | 示例 |
|---|---|---|
feat | 新功能 | feat(payment): add HSBC payment gateway |
fix | Bug 修复 | fix(auth): resolve token refresh race condition |
docs | 文档更新 | docs(api): update SWIFT endpoint documentation |
style | 格式调整 | style(format): format DateTimeUtils |
refactor | 重构 | refactor(validator): simplify amount validation |
perf | 性能优化 | perf(query): add index hint for transaction lookup |
test | 测试 | test(unit): add mock tests for AccountService |
chore | 构建/工具 | chore(deps): upgrade Spring Boot to 3.2 |
revert | 回退 | revert: revert "feat(payment): add webhook" |
security | 安全修复 | security: patch CVE-2026-1234 in auth module |
3.3 自动验证 Commit 格式
# commitlint 配置(commitlint.config.js)
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor',
'perf', 'test', 'build', 'ci', 'chore', 'revert', 'security'
]],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'header-max-length': [2, 'always', 72],
}
};
# .husky/commit-msg(Git hooks,自动检查 commit 信息)
npx husky add .husky/commit-msg 'npx commitlint --edit $1'
4. Code Review 实践:质量门禁
4.1 PR 描述模板
## Summary
<!-- 一句话描述这次变更做什么 -->
## Type
- [ ] Feature / 功能
- [ ] Bug Fix / 修复
- [ ] Refactor / 重构
- [ ] Hotfix / 热修复
- [ ] Security / 安全
## Why
<!-- 为什么要做这个变更,TICKET 链接 -->
## How
<!-- 怎么实现的,关键设计决策 -->
## Testing
<!-- 做了哪些测试,截图/录屏 -->
## Screenshots(UI 变更)
<!-- Before / After -->
## Checklist
- [ ] CI pipeline 全部通过
- [ ] 代码覆盖率未下降
- [ ] 相关文档已更新
- [ ] 安全性自审完成
- [ ] 性能影响评估(如有)
4.2 Review 检查清单
## Review Checklist
### 功能正确性
- [ ] 业务逻辑是否正确实现了需求?
- [ ] 边界条件处理了吗?(空值、超大值、负数)
- [ ] 错误处理完善了吗?
- [ ] 事务边界正确吗?
### 代码质量
- [ ] 变量/函数命名有意义吗?
- [ ] 方法行数合理(< 50 行)?
- [ ] 重复代码抽离了吗?
- [ ] 有没有硬编码的值?
### 安全
- [ ] SQL 注入风险?(用了参数化查询?)
- [ ] 敏感数据暴露?(日志、响应、URL 参数)
- [ ] 权限校验到位了吗?
### 性能
- [ ] 数据库查询有 N+1 问题?
- [ ] 有没有缓存应该加但没加的地方?
- [ ] 大数据量场景考虑了吗?
### 测试
- [ ] 有没有新增单元测试?
- [ ] 测试覆盖率没下降?
- [ ] 边界条件有覆盖?
4.3 GitHub PR 保护规则
# 在 .github branch protection rules 中配置:
# Main branch protection:
# ✓ Require pull request reviews before merging(至少 2 人审批)
# ✓ Dismiss stale reviews when new commits pushed
# ✓ Require status checks to pass before merging(CI 绿灯)
# ✓ Require branches to be up to date before merge
# ✓ Require signed commits(提交必须 GPG 签名)
# ✓ Do not allow force pushes
# ✓ Do not allow branch deletion
5. 合并冲突预防与解决
5.1 预防:频繁合并 + 小步提交
合并冲突的根本原因:分支与 main 偏离太久
预防策略 1:小步提交
❌ 憋一周,一次性提交 50 个文件
✅ 每天提交 3-5 次,每次只做一件事
预防策略 2:频繁 rebase(保持线性历史)
git checkout feature/PROJ-123
git fetch origin
git rebase origin/main # 定期将 main 最新变更 rebase 过来
# 如果有冲突,只在本地解决,不影响他人
预防策略 3:特性分支先测合
在合并前,用 --no-commit 先试合
git merge --no-commit --no-ff origin/main
# 看看有没有冲突,再决定下一步
5.2 解决:merge vs rebase vs squash
# 1. Merge(保留完整历史)
git checkout main
git merge --no-ff feature/PROJ-123
# → 保留所有 commit 记录,历史可追溯
# → 适合:需要完整审计记录的系统(如银行)
# 2. Rebase(线性历史,更干净)
git checkout feature/PROJ-123
git rebase main
# → 将特性分支的提交"重放"到 main 最新提交之上
# → 优点:git log 是线性历史,没有 merge commit
# → 缺点:改写历史,不要在已发布的分支上用
# 3. Squash(合并多个 commit)
git merge --squash feature/PROJ-123
# → 将特性分支的所有 commit 合并成 1 个
# → 优点:main 历史干净
# → 缺点:丢失中间 commit 信息
# 汇丰银行推荐:
# 特性分支合并 → squash(保持 main 历史整洁)
# Release 分支合并 → merge --no-ff(保留发布节点)
# Hotfix 合并 → merge --no-ff(保留热修复历史)
6. 银行合规要求:GPG 签名与审计
# 1. GPG 签名配置(强制要求)
git config --global commit.gpgsign true
git config --global tag.gpgsign true
# 2. 配置签名密钥
git config --global user.signingkey <your-gpg-key-id>
# 3. 签署每次提交(交互式 rebase 时)
git rebase -S HEAD~10 --interactive
# 4. GitHub 设置:强制要求签名
# Settings → Branches → Add rule
# → Require signed commits ✅
# GitHub Actions:验证提交签名(合规要求)
name: Verify Commit Signature
on:
pull_request:
branches: [main, release/*]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify commits are signed
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 -d > signing-key.gpg
git verify-commit HEAD
# 如果签名验证失败,工作流失败
相关阅读:银行科技 CI/CD 流水线设计 · GitOps ArgoCD 银行级部署实战 · 项目可用性-集群高可用设计