Angular 分支策略与版本发布管理指南:理解 main 分支、补丁分支与 npm 分发标签的完整协作机制
本篇技术指南基于 Angular 官方仓库的贡献者文档 contributing-docs/branches-and-versioning.md,系统讲解 Angular 团队如何通过一套与 npm 发布版本强关联的 git 分支体系来组织代码合并、特性冻结与版本发布。读完本文,你将掌握 Angular 的 main 分支与 \d+.\d+.x 补丁分支的命名与职责边界、latest/next/v*-lts 三个 npm 分发标签的语义、主版本从 major 到 minor 再到 RC 的完整发布生命周期,以及作为贡献者如何通过 target: * 标签与 base branch 的搭配,把一次提交精确送达你期望的所有发布分支。
前置知识:理解本指南所需的核心概念
本指南讨论的是 Angular 仓库内部的分支管理与发布协作约定,阅读前提是掌握以下两点背景:
- 语义化版本(Semantic Versioning):即
MAJOR.MINOR.PATCH三段式版本号语义。MAJOR(主版本)引入不向后兼容的变更,MINOR(次版本)以向后兼容方式加入新功能,PATCH(补丁)仅修复 bug。整个分支体系的划分正是围绕这三类变更的落地路径设计的。 - npm 分发标签(distribution tags):npm 包可以同时发布多个版本号,并用人类可读的标签(tag)指代其中某个具体版本。消费者执行
npm install @angular/core时默认安装的版本,由latest标签指向的版本决定;Angular 的分支状态与标签指向互相映射。
在动手贡献前,建议先阅读配套的 triage-and-labelling.md,它描述了同一套 target: * 标签在 issue 与 PR 处理流程中的完整用法,与本指南互为补充。
npm 分发标签:理解分支与版本发布的映射入口
Angular 的分支状态直接对应其发布到 npm 上的版本,整个协作流程围绕以下三类 npm 分发标签展开:
| 标签 | 说明 |
|---|---|
latest |
最新的稳定版本(stable)。普通用户通过 npm install 拿到的是这一版本。 |
next |
最新的预发布版本(pre-release),用于社区提前测试新特性。该标签不一定始终存在。 |
v*-lts |
指定主版本的最新 LTS(长期支持)版本,例如 v9-lts 代表 9.x 系列最新的 LTS 版本。 |
在 Angular 仓库中,这套映射可以借助 package.json 与 CHANGELOG.md 直接观察。以本仓库当前快照为例:package.json 中根包的版本为 22.2.0-next.4,而 CHANGELOG.md 头部同时并列着两条版本的更新记录:22.2.0-next.4(2026-08-26)与 22.1.4(2026-08-26)。这正是"next 预发布版本与 latest 稳定版本并行迭代"在真实仓库中的直接证据——main 分支正在孵化 22.2.0-next 序列,而稳定线 22.1.x 同时持续接收补丁。
分支命名约定:main 分支与版本号 .x 分支
Angular 的分支策略遵循一套非常简单且规律化的命名约定:
main分支:仓库的主干分支,始终代表"绝对最新"的变更。main上的代码永远处于预发布状态(pre-release),通常以next标签发布到 npm。当你看到 package.json 中版本号带有-next.N后缀时,正说明该分支处于这一状态。- 版本号分支:每次主版本或次版本(minor/major)递增时,会以
\d+\.\d+\.x的命名规则(如10.2.x)新建分支,后续该版本范围内的补丁变更统一合入该分支。例如10.2.x分支代表所有以10.2.开头的后续发布所累积的最新补丁。
与 npm 标签对应,凡被标记为 latest 的版本必然对应着某一条这样的 .x 分支,这条分支被称为活动补丁分支(active patch branch)。
该约定在仓库的 git 历史中完全可验证。执行 git branch -a 可看到仓库保留了从 10.0.x 一直到 22.1.x 的全量版本分支,例如:
remotes/origin/15.0.x remotes/origin/15.1.x remotes/origin/15.2.x
remotes/origin/18.0.x remotes/origin/18.1.x remotes/origin/18.2.x
remotes/origin/20.0.x remotes/origin/20.1.x remotes/origin/20.2.x
remotes/origin/20.3.x remotes/origin/21.0.x remotes/origin/21.1.x
remotes/origin/21.2.x remotes/origin/22.0.x remotes/origin/22.1.x
可见每个 minor 版本对应一条 .x 分支,且后续 patch 版本只在此基础上递增。同时注意 CHANGELOG.md 中 22.0.0(2026-06-03)发布后,22.0.1 至 22.0.8(2026-07-22)的补丁序列持续了近两个月,而同期 22.1.0 也于 2026-07-29 发布——新旧版本线并行维护、补丁互相 cherry-pick 的运作由此可以推断。
主版本发布生命周期
节奏总览:从每年两次到每年一次
Angular 大约每十二个月发布一个主版本(major)。从一个 major 到下一个 major,团队沿着一致的固定节奏循环推进,概括如下:
- 主版本发布。此时
main分支代表下一个 minor 版本。 - 八周后,发布一个 minor 版本,
main随即代表再下一个 minor 版本;此过程重复 4 次。 - 又过八周,最后一个 minor 版本发布,
main分支此时代表下一个 major 版本。 - 三个月后,新的 major 版本发布,流程从头循环。
需要特别说明的是历史节奏差异:直到 Angular v22 之前,Angular 每六个月发布一个 major,每个 major 对应 1-3 个 minor 版本。 这一点可从 CHANGELOG.md 的发布记录中直接印证:19.0.0(2024-11-19)、20.0.0(2025-05-28)、21.0.0(2025-11-19)三个 major 几乎精确相隔半年;而 22.0.0 于 2026-06-03 发布、距上一个 major 约 6.5 个月,标志着向"约每年一个 major + 多次 minor"新节奏的过渡,本指南正文描述的即新节奏下的运作方式。
新节奏下的示例推演
以 22.x 系列为例,完整推演一次从 major 到下一个 major 的过程:
- Angular 发布
22.0.0。此时main分支代表22.1.0。 - 八周后,发布
22.1.0,main代表22.2.0。 - 上述步骤持续重复,直至
22.4.0发布,此时main代表22.5.0。 - 又过八周,发布
22.5.0,main代表23.0.0。 - 三个月后,随着
23.0.0的发布,整个周期再次循环。
以仓库真实记录对照:22.1.0 发布于 2026-07-29,距 22.0.0(2026-06-03)恰好约八周,与上述推演的第一步完全吻合;而 CHANGELOG.md 头部当前的 22.2.0-next 序列,正好对应推演中"main 代表 22.2.0"的阶段。整套模型在仓库快照中处于实时演进的被验证状态。
特性冻结与发布候选(Feature freeze & RC)
在 minor 或 major 版本以 latest 标签发布到 npm 之前,必须依次经历**特性冻结(feature freeze)和发布候选(RC)**两个阶段。这一机制保证了 latest 线上版本只包含经过充分收敛与验证的代码:
特性冻结阶段
- 将
mainfork 出针对特定版本的分支,在该版本以latest发布前,不再允许任何新特性进入。 - 该分支随即成为活动 RC 分支(active RC branch)。
- 分支建立的同时,
main立即递增到下一个 minor/major 的预发布版本。 - 特性冻结一周后,从活动 RC 分支发布首个 RC 版本,以
next标签上架 npm。 - 整个周期内,补丁 bug 修复并行地持续合并进三条线:
main、活动 RC 分支以及活动补丁分支。
RC 发布与转正阶段
- 首个 RC 发布后一到三周,活动 RC 分支即以
latest标签正式发布到 npm,该分支同时转为活动补丁分支。 - 此刻不存在活动 RC 分支,直到下一个 minor/major 进入冻结期。
从 CHANGELOG.md 头部可见,22.2.0-next.4 的迭代周期约为每周一个版本(-next.0 2026-07-29 → -next.4 2026-08-26),这正是"预发布版本持续快速迭代、供社区先行测试"的实际写照;待到特性冻结来临,同一条发布线将转入 RC 命名阶段并最终转正为 latest。
如何为 Pull Request 选择目标分支
认识 base branch 与多分支合入机制
每一个 Pull Request 都有一个base branch(目标基线分支),如上图所示,在 GitHub PR 创建界面中它是下拉控件中被高亮的部分。
- base branch 代表"最晚会接收此变更的分支"。绝大多数 PR 应将 base branch 指定为
main。 - 但某些变更会显式地以更早的分支(如
11.1.x)作为 base,目的是修补一个更旧的版本。 - base branch 之外,一批特定的 GitHub 标签(见下文)会控制该 PR 的提交还会被 cherry-pick 到哪些附加分支。
因此一个 PR 实际落入的分支集合 = 其 base branch + 由 target: * 标签决定的 cherry-pick 目标分支。
五类版本目标标签
Angular 用五个标签把 PR 映射到具体的版本目标:
| 标签 | 说明 |
|---|---|
target: major |
包含破坏性变更(向后不兼容的行为或 API 变更)的改动。 |
target: minor |
引入新的、向后兼容的功能。 |
target: patch |
向后兼容的 bug 修复。 |
target: rc |
应当被显式纳入当前活动 release candidate 的改动。 |
target: lts |
面向 LTS 版本的关键安全修复或浏览器兼容性修复。 |
配套约束如下:
- 每个 PR 必须且只能有一个
target: *标签。如果缺失,由 angular 机器人的状态检查将该 PR 标记为 pending(详见 triage-and-labelling.md)。 - 合并时,Angular 的开发工具链(dev tooling)会先把 PR 合并进其 base branch,再依据
target: *标签把对应提交 cherry-pick 到合适的分支。 - 绝大多数 PR 根据改动内容选择
major、minor或patch三者之一;只有在罕见情况下才会使用rc或lts显式瞄准特殊分支。 - 以
target: rc合并的 PR 往往需要在 RC 版本中获得额外测试,因此 PR 作者与 caretaker(看护者)在向 RC 分支合并 PR 后,应考虑发布一个新的-next版本,以便在稳定版正式发布前获得更充分的验证。 - 带
target: major的破坏性变更,只有在main代表下一个 major 版本时才能被合并。这是"major 变更必须等到发布窗口"这一节奏约束在流程层面的强制落地。
两个特殊的目标标签
除上述五类外,还有两个标签不映射到具体版本号,但同样决定了合并目标分支:
| 标签 | 说明 |
|---|---|
target: automation |
由 angular-robot 账号做出的自动化变更。 |
target: feature |
需要在某个 feature 分支上落地的改动。 |
其中:
target: feature服务于那些游离在常规分支合并流程之外的 feature 分支变更,在 triage-and-labelling.md 中也有对应说明,即允许仅合入 feature 分支、不进入任何常规发布线。target: automation只有angular-robot账号能够使用,且仅以 GitHub UI 中定义的分支为合并目标,不触发跨分支的自动 cherry-pick。配合 triage-and-labelling.md 中对 ng-bot/robot 状态检查的描述,可看出该标签是机器人在自动同步、自动升级等场景下专用的通道。
实战决策表:六类典型 PR 应如何打标
原文档给出了六种最常见的实操场景。下表直接汇总"我想做的事 → 应选的 base branch → 应打的标签 → 变更最终落入哪些分支",供贡献者提交 PR 时对照决策:
| 我想…… | 目标分支(base) | 目标标签 | 我的变更将落入…… |
|---|---|---|---|
| 做一次向后兼容的 bug 修复 | main |
patch |
main、活动补丁分支,以及活动 RC 分支(若存在) |
| 引入一个新特性 | main |
minor |
main(任何时间均可合并) |
| 做一次破坏性变更 | main |
major |
main(仅当 main 代表下一个 major 版本时) |
| 做一次关键安全修复 | main |
lts |
main、活动补丁分支、活动 RC 分支(若存在),以及 LTS 窗口内所有版本的对应分支 |
| 提升某个 RC 的版本号 | 活动 RC 分支 | rc |
活动 RC 分支 |
| 修复某个 major 特性的 RC bug | main |
rc |
main 与活动 RC 分支 |
在 RC 期间把 bug 修复回退到 latest npm 版本 |
活动补丁分支 | patch |
仅活动补丁分支 |
这张表揭示了几个值得注意的设计细节:
patch的多点开花:向后兼容的 bug 修复会被同步到main+ 活动补丁分支 + 活动 RC 分支。这与 CHANGELOG.md 中观察到的现象互相印证——例如最新头部记录里22.2.0-next.4与22.1.4两个并行版本段中出现了描述几乎一致的修复条目(如避免原型成员冲突、number 格式化等),从 changelog 结构可以推断同一类修复正被同步合入next线与当前补丁线。lts的宽覆盖:关键安全修复会穿透 LTS 窗口内的所有版本分支,这是 LTS 承诺"为历史版本持续提供安全补丁"的工程化实现。根据 triage-and-labelling.md 的补充说明,target: lts的 PR 需要直接在 GitHub UI 中指定具体要合入的 LTS 分支;若一个修复需要进入多个 LTS 分支,则需要为每个 LTS 分支分别创建独立 PR。rc的两种形态:既可以直接以活动 RC 分支为 base 做版本号 bump,也可以main为 base 提交修复后由工具自动同步到 RC 分支。- "仅合入旧分支":若希望某个 patch/RC 变更只落在补丁/RC 分支、而不进入
main,可在 GitHub UI 中直接以该补丁/RC 分支为 base,并搭配相应target: patch/target: rc标签——这正是维护历史版本时最常用的操作姿势。
结合仓库源码与工具链的进一步印证
若想深入确认整套机制在工程层面的落地,可从以下仓库位置继续阅读:
- contributing-docs/branches-and-versioning.md:本指南原始出处,包含最权威的流程定义。
- contributing-docs/triage-and-labelling.md:同一套
target: *标签在 issue 分流与 PR 合并(含 caretaker 三检、action: merge、robot 状态检查)中的详细规则,是理解"标签如何驱动自动化"的必读补充。 - CHANGELOG.md:真实的版本发布流水账。头部并列的
-next.N、latest补丁序列以及 major 的时间戳,就是本文所述生命周期与多分支并行机制的实时证据。 - package.json:根包
version字段当前指向22.2.0-next.4,直观展示main分支"永远是预发布版本"的状态。
在本地验证分支与版本快照,可执行以下只读命令:git branch -a(查看全部 .x 分支)、git tag(查看各发布标签)、git log --oneline(查看 main 的最新提交)。综合本文的分支命名约定、生命周期节奏与标签决策表,即可精确判断任何一次代码变更应当以哪个分支为 base、应打哪个 target 标签,以及合并后该变更将抵达哪些 npm 发布线。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
