# 分支策略

> 弄清从哪里拉分支、合并到哪里、最终发布什么。

开始项目任务 · /zh/branching-strategy/ · 2026-11-05

## 让 AI agent 核对你的分支计划

**Prompt**

```text
通过已连接的 Jira MCP 或已认证的 acli 读取 [Jira 编号或链接]，包括描述、验收标准和评论。
访问不了的话，让我把 ticket 内容贴给你。
以 ticket 的 Fix Version 作为目标版本；没有设置的话，先问我，再选分支。查看仓库说明和分支历史。
告诉我起始分支、PR 目标分支，以及是否需要 Release Merge 分支。
指出会被连带进来或被排除的 ticket。说明远程分支是否已经是最新。
先不要切分支、合并或 push。
```

- 动手之前，先对照下面的分支规则核对这个计划。
- 新工作从 `main` 拉分支；`main` 是生产代码的基线。
- 每个 ticket 的代码和测试放在一起；批准的 ticket 汇总到 release 分支上。
- 生产环境检查通过后，把已发布的代码合并进 `main`。文档单独更新。
- 所有改动都走评审过的 PR。不要直接 commit 到 `main` 或 `release/*`。

## 认识各类分支

- `ENG` 是示例 Jira 项目 key，`ENG-123` 和 `ENG-124` 是 ticket。换成你自己的 ticket 编号。
- `RM1` 表示这个 ticket 的第一个 Release Merge 分支。

| 分支                                 | 用途                                   |
| ---------------------------------- | ------------------------------------ |
| `main`                             | 合并回来之后的最新已发布代码，新工作从这里开始。之后的发布收尾只改文档。 |
| ticket — `feat/ENG-123`            | 单个 ticket 的代码和测试，不夹带无关 ticket。       |
| release — `release/2.8.0`          | 选进这次发布的 ticket；在获得批准并发布之前，它都是候选版本。   |
| Release Merge — `feat/ENG-123-RM1` | 临时的集成分支，用来解决和 release 分支之间的冲突。       |
| 修复 — `fix/ENG-130`                 | 紧急的生产修复，或者修复一个没有 ticket 分支的候选版本缺陷。   |

## 选好起始分支和 PR 目标分支

| 你的改动                         | 从哪里拉分支           | PR 合到                                        |
| ---------------------------- | ---------------- | -------------------------------------------- |
| 计划内的 ticket                  | 当前的 `main`       | 目标版本的 release 分支                             |
| 发布前修复你自己的 ticket             | 继续在原 ticket 分支上改 | 目标版本的 release 分支；用了 Release Merge 分支的话，经由它合入 |
| 候选版本里的缺陷，且没有现成的 ticket 分支可以修 | 从这个候选版本新拉一个修复分支  | 同一个 release 分支                               |
| 紧急生产修复                       | 当前的 `main`       | 单独的补丁 release 分支                             |

- ticket 在 Jira 上的 Fix Version 就是它的目标版本。没有设置或有变动时，先和 PM 确认，再拉分支。
- 从 `main` 拉分支前，确认最近一次生产发布已经合并回来。否则 `main` 落后于生产环境，基于它做的紧急修复，发出去的代码会和线上运行的不一样。
- 从候选版本拉出的修复分支，会带上这个候选版本里的所有 ticket。不检查这些依赖，就不能把它挪到另一个候选版本。

## 跟着一个 ticket 走完发布

图示: 第 1 步：从 main 创建 ticket 分支和 release 分支。第 2 步：把 ticket 合并进 release 分支。第 3 步：验证候选版本。第 4 步：批准并部署测试过的 artifact，然后验证生产环境。第 5 步：把 release 分支合并进 main。之后单独做文档收尾。

_先验证，再部署，最后把已发布的代码合并进 main。_

1. **开发。** 从与生产环境一致的 `main` 创建 ticket 分支和 release 分支。
2. **集成。** 把批准的 ticket PR 合并进目标版本的 release 分支。
3. **验证。** 通过必需的检查；记下测试过的 commit 和 artifact。
4. **部署并验证。** 获得批准后部署测试过的 artifact，再检查生产环境的版本和改动过的流程。
5. **合并回 main。** 通过 PR 把已发布的代码合并进 `main`，然后完成[文档收尾](/zh/release-mgmt/)。

## 解决冲突，不混入其他 ticket 的代码

- 在 Release Merge 分支上解决和 release 分支的冲突。
- 原 ticket 分支里不要混进无关 ticket。

图示: 第 1 步：从 ticket 分支创建 RM1。第 2 步：把 release 分支合并进 RM1 并解决冲突。第 3 步：如果测试发现 ticket 缺陷，在原 ticket 分支上修复，再合并进 RM1。第 4 步：测试 RM1，通过评审过的 PR 合并进 release 分支。永远不要把 RM1 合并回 ticket 分支。

_在 RM1 上解决冲突；业务代码的修复留在 ticket 分支上。_

1. **创建 RM1。** 从 `feat/ENG-123` 拉出 `feat/ENG-123-RM1`。
2. **解决冲突。** 把 release 分支合并进 RM1 并解决冲突。不要加入新的业务行为。
3. **在 ticket 分支上修复。** ticket 缺陷在原分支上修，再合并进 RM1。不需要修复就跳过。
4. **评审并合并。** 测试合并后的结果，然后从 RM1 向 release 分支提 PR。

- 不要直接在 RM1 上开发业务代码修复，也不要 cherry-pick 过来。
- 不要把 RM1 合并回 ticket 分支：它现在已经包含 release 分支里的其他 ticket。

## 移除 ticket：重建候选版本

- 旧候选版本包含 `ENG-123` 和 `ENG-124`。
- 如果 `ENG-124` 推迟，就从 `main` 重建，只放 `ENG-123`。
- `ENG-124` 留在它自己的 ticket 分支上，把它的 Jira Fix Version 改到后面的发布。

图示: 第 1 步：ENG-123 和 ENG-124 都已合并进旧候选版本；ENG-124 推迟后，停止使用这个候选版本。第 2 步：从 main 创建替代的 release 分支。第 3 步：只集成 ENG-123，需要时使用新的集成分支。第 4 步：重新验证，并为替代的 commit 和 artifact 取得批准；不要发布已被取代的候选版本。

_左：ENG-123 和 ENG-124 都进了旧候选版本。右：新候选版本只收 ENG-123。_

1. **废弃旧候选版本。** 把 `release/2.8.0` 标记为已取代，不再部署到任何环境。
2. **重新开始。** 从当前的 `main` 创建 `release/2.8.0-2`。
3. **只放 ENG-123。** 通过 PR 合并 `ENG-123`。使用新的 Release Merge 分支；旧的会把 `ENG-124` 带回来。
4. **重新验证。** 对替代的 commit 和 artifact 重新测试、重新批准。`ENG-123` + `ENG-124` 一起的测试结果，证明不了 `ENG-123` 单独能用。

- 只在旧候选版本上做过的修复，先检查依赖，再通过新的 PR 带到新候选版本里。

## 处理紧急生产修复

- 给修复单独一个版本号。如果生产环境是 `2.7.0`，就从 `main` 创建 `release/2.7.1`。
- 从 `main` 拉出 `fix/ENG-130`，向 `release/2.7.1` 提 PR。验证、部署、合并回 `main`，和普通发布一样。
- 不要从正在进行的候选版本（比如 `release/2.8.0`）拉修复分支，也不要直接合并到那里：候选版本里有还没发布的 ticket。
- 在修复之前切出的候选版本不包含这个修复。补丁发布合并回 `main` 之后，通过评审过的 PR 把 `main` 合并进候选版本，并重新验证；否则这次发布会把缺陷带回来。

下一步：分支和 PR 目标分支确定后，开始[交付改动](/zh/deliver-a-change/)。
