跳转至

Git 分支与部署指南

给所有开发者看。5 分钟读完,知道怎么安全开发和部署。


一句话原则

main 分支永远可以安全部署。不要把半成品代码 merge 到 main。


我们的部署流程

graph LR
    A[feature branch] -->|PR + review| B[main]
    B -->|自动| C[test 环境<br/>us-west-2]
    B -->|手动触发| D[pre 环境<br/>us-east-2]
    B -->|手动触发<br/>需确认| E[prod 环境<br/>us-east-1]

    style C fill:#d4edda
    style D fill:#fff3cd
    style E fill:#f8d7da

日常开发:三步走

1. 建分支

git checkout main && git pull
git checkout -b feature/简短描述

2. 每天同步 main

git fetch origin && git rebase origin/main

这一步防止冲突累积。每天做一次,冲突永远很小

不 rebase(冲突累积):
main:        ──A──B──C──D──E──
你的 branch:   └──X──Y──Z──        ← 基于 A,跟 main 差了 4 个 commit,冲突爆炸

每天 rebase(零冲突):
main:        ──A──B──C──D──E──
你的 branch:                └──X──Y──Z──   ← 基于 E,始终最新,冲突为零

3. 提 PR

gh pr create --base main --title "feat: 描述"

PR 必须:CI 通过 + CDK diff 无危险变更 + code review 通过。


怎么拆大 Feature

关键:每个 PR 独立 merge 后,不能让现有功能出问题。

❌ 错误:一个大 PR
──────────────────────────────────────────────────
PR #1: DynamoDB + SQS + Lambda + 全部逻辑 (2000 行)
       merge 后半成品上线,出问题难回滚

✅ 正确:拆成 4 个安全的小 PR
──────────────────────────────────────────────────
PR #1: 加 DynamoDB table              (200 行) → merge ✅  空 table 不影响现有功能
PR #2: 加 SQS queue + DLQ             (200 行) → merge ✅  空 queue 不影响现有功能
PR #3: 加 Lambda (DRY_RUN=true)       (400 行) → merge ✅  存在但不工作
PR #4: 启用 Lambda (DRY_RUN=false)     (50 行) → merge ✅  feature 正式上线

怎么判断"能不能 merge"

场景 能 merge 吗 原因
加了 DynamoDB table,还没有代码读写它 空 table 不影响任何功能
加了 Lambda,设了 DRY_RUN=true Lambda 存在但不工作
改了 Lambda handler 逻辑,只改了一半 半成品逻辑会破坏正在处理的数据
改了 API 返回格式,调用方还没适配 调用方会报错

改现有代码又没法拆? 用 feature flag:

// CDK 里先设 'false',merge 后走旧逻辑,不影响现有功能
// 等 feature 做完再改成 'true'
if (process.env.ENABLE_NEW_ANALYSIS === 'true') {
  return newLogic(data);
} else {
  return oldLogic(data);  // 现有功能不受影响
}

大 Feature 用 Draft PR

当 feature 需要多天开发、无法一次性拆成小 PR 时,先开 Draft PR:

# 第一次 push 后立即开 Draft PR
gh pr create --draft --base main --title "feat: 描述"

# 每天继续开发 + push,review comments 在 PR 上积累
git push

# 全部做完后,转为 Ready for Review
gh pr ready <PR号>

为什么用 Draft PR 而不是做完再开?

做法 问题
做完再开 PR 一次性 review 几千行,reviewer 痛苦,容易漏看
边做边开 Draft PR reviewer 可以分批看,早期发现设计问题,避免返工

Draft PR 的好处: - GitHub 不允许 merge Draft PR,不会被误操作 - 保留完整 review 历史,不会因为 close/reopen 丢失上下文 - 队友能随时看到进度,提前提出意见 - CI 照常跑,随时知道 build 状态


紧急 Hotfix 流程

当 prod 出 bug 需要紧急修复时,按以下 5 步操作:

从 prod tag 切分支 → 修 bug → 部署到 test 验证 → 部署到 prod → 合并回 main
# ① 从 prod 当前版本切分支(不是从 main 切!main 上可能有新代码)
git tag --list 'prod-*' --sort=-creatordate | head -5   # 查看最近的 prod tag
git checkout -b hotfix/简短描述 prod-2026-03-04          # 从 tag 切

# ② 修 bug
git add 具体文件
git commit -m "fix: 简要描述"
git push -u origin hotfix/简短描述

# ③ 部署到 test 验证
gh workflow run deploy-test.yml -f ref=hotfix/简短描述

# ④ 验证通过后部署到 prod
gh workflow run deploy-prod.yml -f confirm=deploy-prod -f ref=hotfix/简短描述

# ⑤ 合回 main(不能忘!否则下次部署会覆盖 hotfix)
gh pr create --base main --head hotfix/简短描述 --title "fix: 合并 hotfix 回 main"

为什么从 tag 切而不是从 main 切? 因为 main 上可能有还没部署过的新代码。从 prod tag 切,保证 hotfix 分支和当前生产环境一致,不会带上任何半成品。


好习惯 vs 坏习惯

❌ 坏习惯 ✅ 好习惯 为什么
半成品赶紧 merge,怕冲突 留在 branch 上,每天 rebase main 永远干净,冲突不累积
一个大 PR,2000 行 拆成小 PR,每个独立安全 好 review,好回滚
一周不 rebase 每天 git rebase origin/main 冲突在小的时候就解决
hotfix 从 main 切 hotfix 从 prod tag 切 不会带上 main 上的新代码
部署完不打 tag 每次 prod 部署自动打 tag 永远知道 prod 跑的是哪个版本
--no-verify 跳 hooks 修复 hook 报的错 不绕过类型检查和测试
hotfix 忘了合回 main 部署后立即创建 PR 合回 下次部署不会覆盖 hotfix

速查:常用命令

我要做什么 命令
建 feature 分支 git checkout -b feature/描述
每天同步 main git fetch origin && git rebase origin/main
rebase 遇到冲突 解决冲突 → git add 文件git rebase --continue
rebase 搞乱了想撤回 git rebase --abort
提 PR gh pr create --base main --title "feat: 描述"
部署 test(指定分支) gh workflow run deploy-test.yml -f ref=分支名
部署 prod gh workflow run deploy-prod.yml -f confirm=deploy-prod
部署 prod(指定分支) gh workflow run deploy-prod.yml -f confirm=deploy-prod -f ref=分支名
查看 prod tag git tag --list 'prod-*' --sort=-creatordate \| head -5

常见问题

Q:merge 和 rebase 什么时候用哪个?

简单记:同步自己的 branch 用 rebase,合并到 main 用 PR merge。

我要做什么 用什么
把 main 最新代码同步到我的 feature branch git rebase origin/main
把我的 feature branch 合并到 main GitHub PR → 点 Merge

Q:prod tag 从哪来?

每次成功部署 prod 后,CI 自动打 tag(格式 prod-YYYY-MM-DD)。手动打:

git tag prod-2026-03-04 && git push origin prod-2026-03-04