Moby 补丁发布流程解析:release 分支、Backport 规则与 cherry-pick 标签体系
Moby(Docker Engine 的上游项目)采用「master 直接出包 + 按需建立 release 分支」的补丁(patch/bugfix)发布策略,补丁必须满足"非新功能、不破坏现有功能、属于 bug 修复或小改进"三条标准,并通过 process/cherry-pick/<分支名> 标签驱动 backport 流程。本文以官方文档 PATCH-RELEASES.md 为核心,结合仓库中的分支规范、标签约定与 releases/scripts 下的同步脚本,完整梳理补丁从 master 到发布分支的落地路径。
何时可以直接从 master 切补丁版本
官方规则的第一条(见 PATCH-RELEASES.md)非常简洁:
如果
master分支上没有"不适合打进补丁版本"的变更(即不会促使发布一个非补丁版本的新版本),补丁版本可以直接从master分支切出。
这意味着 Moby 并没有强制要求每个补丁版本都走 release 分支。只要 master 上的在研变更与当前补丁目标不冲突,维护者直接基于 master 打 tag 即可,无需任何 backport 操作。这也是 RELEASE-PROCESS.md 中 "When possible, releases are cut directly from master" 思想的延续。
何时需要创建 release 分支
一旦 master 上存在不适合进入补丁版本的变更(例如未定型的大特性、需要更长评审周期的重构),就需要为当前维护的版本线创建 release 分支,补丁版本改为从该分支切出。分支模型在 BRANCHES-AND-TAGS.md 中有完整定义:
- 分支命名格式:Docker Engine 的 release 分支使用
docker-MAJOR.x格式,例如docker-29.x承载整个 29 大版本及其所有小版本的发布周期。历史上的26.0、26.1分支则是按"单个小版本"建分支的旧做法,具体采用哪种粒度由该分支的赞助维护者(sponsoring maintainers)决定。 - 维护者责任:release 分支的赞助维护者是首要联系人,负责指导向该分支的变更贡献。
- 当前维护状态:从源码中的分支状态表看,
docker-29.x由 Moby 项目维护者(MAINTAINERS)维护,支持到docker-30.x之后;25.0分支由社区维护者维护,已知到期日为 2026-12-04;docker-28.x、27.x、26.1、26.0、24.0、23.0及更早分支均已不再维护。 - 贡献状态三档(对贡献者预期具有信息性意义):
- Maintained:维护者积极开发,接受贡献与 backport,在安全公告覆盖范围内;
- Maintained (security):不再积极开发,仅可能接受关键安全问题的 backport,仍在安全公告范围内;
- Unmaintained:不再开发,不接受贡献,超出安全公告范围。
版本基线本身也记录在 releases/versions.yaml 中,例如当前 Docker 最近发布为 29.7.2、下一计划版本为 29.8.0,可作为"当前补丁线"的参考锚点。
Backport(回合)规则与补丁准入标准
当 release 分支存在时(因为 master 上有不适合补丁版本的变更),所有 bug 修复与补丁必须 backport 到该 release 分支;如果补丁直接来自 master,则不需要 backport。这是文档中"Backporting changes"一节的核心逻辑。
一个补丁要进入 release 分支,必须同时满足以下三条标准(PATCH-RELEASES.md):
- 不能是重大功能或新功能(Not be a major/new feature);
- 不能破坏现有功能(Not break existing functionality);
- 必须是一个 bug 修复或小改进(Be a bugfix or a small improvement)。
这实际上把 release 分支定位为"稳定性优先"的通道:任何会改变对外行为面的变更都被排除在外,只有回归性质的修复才能流入。
cherry-pick 标签:标记 PR 进入下一个补丁版本
流程的最后一步落在 Pull Request 的标签操作上。对于提交到 master 分支、需要进入下一个补丁版本的 PR,作者或维护者应为其打上 process/cherry-pick/<BRANCH_NAME> 标签,其中 <BRANCH_NAME> 对应目标 release 分支名。
从 REVIEWING.md 的 Process labels 表可以看到这套标签在评审工作流中的完整配套定义(Process labels 专用于辅助补丁发布准备,且只应用于 PR):
| 标签 | 用途 |
|---|---|
process/cherry-pick |
应在 bump/release 分支上被 cherry-pick 的 PR,且必须同时分配 milestone |
process/cherry-picked |
已完成 cherry-pick 的 PR,便于查找已进入 RC 的 PR 并更新 changelog |
process/docs-cherry-pick |
应在 docs 分支 cherry-pick 的文档类 PR(仅针对当前发布周期的文档修改、通用 Markdown/拼写修复) |
process/docs-cherry-picked |
已在 docs 分支完成 cherry-pick |
process/merge-to-master |
直接开在 bump/release 分支上、但还需要回合回 master 的 PR |
process/merged-to-master |
已回合回 master 的 PR |
注意 process/merge-to-master 与 process/merged-to-master 构成反向闭环:当修复只能先落在 release 分支(典型场景是线上问题先于 master 修复)时,必须显式标记"待回 master / 已回 master",避免 release 分支上的修复在 master 上丢失。从这套标签结构看,Moby 的 backport 是双向的:master → release 分支走 cherry-pick,release 分支 → master 走 merge-to-master。
配套脚本:sync-branch 与 unmerged-tags
仓库 releases/scripts 目录下有两个与补丁同步直接相关的 shell 脚本,是上述流程的落地工具。
unmerged-tags:列出 release 分支缺少的发布 tag
unmerged-tags 的用法为 unmerged-tags <RELEASE_BRANCH> <TAG>,逻辑上做了三层校验:
- 目标 tag 必须存在,且必须是
master(优先upstream/master,其次origin/master)的祖先; - 如果 tag 已包含在 release 分支中,直接返回;
- 否则按版本排序(通过
versionsort.suffix=-alpha./-beta./-rc.保证预发布版本正确排序)列出所有"已并入 master 但未并入 release 分支"的docker-v*tag,输出到指定 tag 为止:
git -c versionsort.suffix=-alpha. \
-c versionsort.suffix=-beta. \
-c versionsort.suffix=-rc. \
tag --merged "$master" --no-merged "$release_branch" \
--sort=v:refname \
--format='%(refname:short)' \
'docker-v*' \
| awk -v tag="$tag" '{print} $0==tag{exit}'
(见 unmerged-tags)。这相当于为 release 维护者生成一份"待同步补丁清单",恰好对应 PATCH-RELEASES 文档中 backport 一节的操作场景。
sync-branch:把发布 tag 合入 release 分支
sync-branch 接收一个或多个 tag,逐个执行 git merge --no-ff;若合并产生冲突,则以 tag 的内容为准(git checkout <tag> -- '.')完成合并——这在 tag 之间内容单调递增的前提下是合理策略。最后用 git merge-base --is-ancestor 逐一校验每个 tag 确实已包含在当前分支中,防止"合了但没真正并入"的静默失败:
for tag_to_sync in "${tags_to_sync[@]}"; do
if ! git merge-base --is-ancestor "$tag_to_sync" HEAD; then
echo "tag $tag_to_sync is not contained in $(git rev-parse --abbrev-ref HEAD)" >&2
exit 1
fi
done
(见 sync-branch)。
两个脚本配合的典型工作流是:先跑 unmerged-tags 得到待同步的 tag 列表,再用 sync-branch 一次性把它们合入 release 分支并做祖先校验。
标签(Tag)与多组件版本规范
补丁最终落地为 tag。按照 BRANCHES-AND-TAGS.md 的约定,仓库遵循语义化版本,tag 通用格式为 vX.Y.Z[-suffix[N]](X/Y/Z 必须齐全;1.8.0 的第一个候选版为 v1.8.0-rc1,产品的第二个 alpha 为 v1.0.0-alpha1)。由于仓库包含多个独立版本化的组件,tag 前缀也按组件区分:
| 组件 | Tag 格式 | 示例 |
|---|---|---|
| Moby(核心库,当前处于 v2.x beta) | vX.Y.Z |
v2.0.0-beta.5 |
| Docker Engine | docker-vX.Y.Z |
docker-v29.1.2 |
API(api/ 独立 Go module) |
api/vX.Y.Z |
api/v1.52.0 |
Client(client/ 独立 Go module) |
client/vX.Y.Z |
client/v1.52.0 |
其中 unmerged-tags 脚本过滤 docker-v* 的行为,正对应上表中 Docker Engine 组件的 tag 前缀。API 与 Client 子模块的发布配置分别存放在 api/releases/v1.52.0-beta.toml 与 client/releases/v0.1.0-beta.toml,其中的 sub_path、previous、pre_release 字段用于生成子模块的发布说明(例如 API 说明中写明"该发布延续 1.x API 兼容性线的第 52 个 minor 版本")。需要说明:Moby 项目只提供源码(tag)发布,二进制发行版来自各贡献方,已知发行渠道可在 PACKAGERS.md 中查阅。
与九周发布周期的关系
补丁发布不是孤立流程。RELEASE-PROCESS.md 描述了完整的项目发布节奏:九周为一个发布周期,前六周为开发评审期(新特性与 bug 修复均有资格进入下一版本),第六周起代码冻结并产生 Release Candidate(RC),冻结期内 master 继续正常开发但 RC 不再接受新特性——在 master 上修复的 bug,由 release owner 选择性地 cherry-pick 进 RC,随着 RC 变化再发布新的 RC 供社区测试,第九周统一发布。
对照本文主题可以这样理解两者的分工:
- 冻结期内的 RC 维护:cherry-pick 的对象是 RC(本质是 master 的快照分支),目的是让即将发布的版本收敛;
- 补丁版本维护:cherry-pick 的对象是长期存在的 release 分支(如
docker-29.x),目的是让已发布的版本线持续获得 bug 修复。
两者共用同一套 process/cherry-pick* 标签体系与"补丁准入三标准",区别只在于目标分支的生命周期长短。
实践要点小结
- 优先从 master 出补丁:仅当 master 上的在研变更与补丁目标冲突时才建 release 分支(
docker-MAJOR.x格式); - 补丁准入三标准:非新功能、不破坏现有功能、属 bug 修复或小改进,三者缺一不可;
- 用标签驱动 backport:给 master 上的 PR 打
process/cherry-pick/<release 分支名>,完成后打process/cherry-picked以便更新 changelog; - 反向闭环:先落在 release 分支的修复要用
process/merge-to-master/process/merged-to-master保证回灌 master; - 用脚本做同步与校验:
unmerged-tags <分支> <tag>生成待同步清单,sync-branch TAG...执行合并并以祖先关系校验结果; - 按组件打 tag:Docker Engine 用
docker-vX.Y.Z,API/Client 子模块用api/vX.Y.Z、client/vX.Y.Z,版本基线以 releases/versions.yaml 为准。
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 StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00