- 编程语言
- 编译器
- 语言运行时
- 标准库
- 开发工具
【免费下载链接】sdk
The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
导读
本文基于 Dart SDK 官方发布流程文档,系统讲解如何将一个已经在main分支上修复的 bug,通过 cherry-pick(遴选)机制合入beta或stable发布分支,从而进入下一个热修复(hotfix)版本。读完本文,你将掌握完整的 cherry-pick 操作链路:判断是否需要回移、创建与提交遴选变更列表(changelist)、编写合规的提交信息与 CHANGELOG 条目、通过 Gerrit 提交队列上线,以及当修复涉及third_party依赖时的特殊处理流程。文档对应的原始资料位于 docs/Cherry-picks-to-a-release-channel.md。
一、什么是 Cherry-pick:从 main 到发布分支的定向修复
Cherry-picking 指的是从主开发分支(main)中挑选一个已经存在的 bug 修复提交,将其合并到发布分支(如beta、stable),以便纳入下一个热修复版本的发布流程。
Dart SDK 采用多分支并行开发与发布模型,docs/Branches-and-releases.md 中给出了清晰的分支职责划分:
- main:日常开发主干,所有 CL 在此落地;
- dev:由 main 全量推送填充,通常每周两次,仅紧急情况才使用 cherry-pick;
- beta:由 dev 全量推送或通过 cherry-pick 填充,通常每月一次,不要直接在此提交 CL;
- stable:主发布分支,由 beta 全量推送或 cherry-pick 填充,同样禁止直接落地 CL。
重要前提:cherry-pick 流程仅适用于 bug 修复和回归(regression)修复。新功能(feature work)不在此流程考虑范围内,需要等待下一个正式版本发布。每次发布周期的最后约两周会进入所谓 "cherry-pick season"(热修复季),此时对 beta 通道只遴选关键修复,每周可能产生多批 cherry-pick。
二、第一步:判断一个修复是否需要 Cherry-pick
触发 cherry-pick 的完整判断流程如下:
- 解决 issue 并在 main 分支落地修复,同时附带测试,以确认问题确实被修复;
- 确认问题是否存在于最新的 beta 与 stable 版本中;
- 评估修复是否值得回移(backport):如果两个通道(beta 和 stable)都受影响,则可能需要提交两份 changelist(分别针对 beta 和 stable)。
只有经过上述评估确认值得回移的修复,才进入正式的 cherry-pick 操作。
三、核心操作:如何 Cherry-pick 一个 Changelist
3.1 创建遴选分支并执行提交遴选
在 SDK 检出目录中,将目标提交($commit)遴选到一个以origin/stable(或origin/beta)为上游的新分支:
$ git fetch $ git new-branch --upstream origin/stable cherry # 或 origin/beta $ git cherry-pick --edit $commit $ $EDITOR CHANGELOG.md # 仅 stable 需要,详见下文其中:
git new-branch是 Google 的 depot_tools/git 辅助命令,用于创建并切换到以origin/stable为上游的新分支cherry;git cherry-pick --edit在应用提交的同时打开编辑器,强制你修订提交信息(这正是提交信息合规所必需的);- 如果同时面向 beta 和 stable 两个通道,则需要在两个分支上分别执行上述流程。
3.2 修订提交信息:四个必改项
遴选后的提交信息必须按以下规则修订:
- 在第一行行首添加
[beta]或[stable]Gerrit 主题标签(hashtag),以便评审者一眼识别这是面向发布分支的遴选; - 将原提交的
Reviewed-on字段重命名为Cherry-pick,用于链接到被遴选的原始 changelist; - 删除新 changelist 中不成立的冲突字段:
Change-id、Commit-queue、Reviewed-by; - 在描述中补充以下五段信息:
- Issue description:问题描述(问题是什么?影响哪些平台?)
- What is the fix:修复内容简述
- Why cherry-pick:说明回移理由、受影响用户与功能性问题
- Risk:本次遴选伴随的风险
- Issue link(s):原始 issue 的链接
3.3 提交信息示例
[stable] Fix foo crash. Issue description: When attempting to use foo under certain conditions, users are unable to compile. What is the fix: foo is now evaluated at runtime. Why cherry-pick: Users of foo are no longer able to compile to bar. Risk: Low, this fix has landed on the main channel and is tested on the same infrastructure. Issue link(s): https://github.com/dart-lang/sdk/issues/12345678 Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/123456783.4 Gerrit 侧元数据要求
Gerrit-Submit-Requirements.md 从评审系统角度进一步补充了元数据规范:
- 面向 stable 和 beta 分支的所有 CL 都要走 cherry-pick 审批流程;
- 提交信息必须包含
[stable]或[beta]hashtag; Cherry-pickfooter 必须链接到 main 分支上的原始评审;若一次遴选捆绑了多个变更,可多次使用该 footer;如果该变更是原创而非从 main 遴选,则需要说明原创理由——footer 的目的是帮助评审者理解原始变更、确认其在发布分支上是安全的;Cherry-pick-requestfooter 必须链接到批准该遴选理由的 GitHub issue,用于在提交前确认已获得批准;- 提交信息中不得保留原提交的
Reviewed-on、Reviewed-by、Commit-Queuefooters,新的 footers 会在提交时自动生成。
四、CHANGELOG:stable 遴选的强制要求
4.1 为什么必须写
stable 通道的 cherry-pick必须在 CHANGELOG.md 中添加条目说明变更内容。原因很直接:发布工程师没有你的全部上下文,他们依赖 CHANGELOG 来撰写发布说明。beta 版本则不需要changelog 条目。
如果CHANGELOG.md中还没有下一个 stable 热修复版本的小节,需要新增一个小节并递增补丁号(例如3.0.4→3.0.5),不写日期。如果某个小节已带有发布日期,说明该版本已经发布,不应再修改——发布日期会在 stable 版本正式编写、确定发布时间时补上。
4.2 标准条目格式
## 3.0.5 This is a patch release that: - Fixes all bugs in the Dart SDK (issue [#123456]) [#123456]: https://dart-review.googlesource.com/c/sdk/+/123456 ## 3.0.4 **Released on:** 2025-01-08 This is a patch release that: ...4.3 豁免情况
如果该遴选仅涉及基础设施、对用户不可见,可以使用Changelog-Exempt: ...footer 豁免 changelog 要求。同样地,Gerrit-Submit-Requirements.md 中说明:基础设施类对用户不可见的变更可用Changelog-Exempt: ...说明为何不需要 CHANGELOG 条目。
版本号侧证:仓库中的 tools/VERSION 文件注释记录了版本演进规则——"Making cherry-picks to stable channel" 时递增PATCH(即3.0.4→3.0.5),"Doing a cherry-pick to trunk" 时递增PRERELEASE_PATCH。这从版本管理层面印证了本文档描述的补丁号递增规则。
五、上传与提交:Gerrit 评审与提交队列
5.1 上传 changelist
使用 depot_tools 的上传命令将遴选 changelist 提交到 Gerrit 等待审批:
git cl upload上传后,先触发一次commit queue 干跑(dry run),并添加合适的 try builders,以确认修复在发布分支上是正确的。
5.2 提交与回归防护
遴选 changelist 需经过**领域主题专家(area subject matter expert)与Dart 团队负责人(Dart team lead)**的双重评审后,由遴选作者提交到 commit queue。提交队列的 try jobs 会将测试结果与 beta/stable 分支上的上一个提交进行对比,一旦引入任何回归即判定失败。
特殊情形:如果必须引入回归,或 try builders 无法在较旧的 beta/stable 代码上运行,可以绕过提交队列,在 Gerrit 中通过强制提交(... -> Submit)完成上线。
六、进阶场景:Cherry-pick 依赖仓库中的单个提交
当修复涉及third_party下的依赖仓库(例如third-party/pkg/pub)中的单个提交时,流程有所不同,需要先在依赖仓库中完成遴选、推送,再通过 SDK 的 DEPS 版本提升(bump)机制把发布分支指向新提交。
6.1 在 SDK 检出中定位依赖当前修订
dart-sdk/sdk/ > git checkout beta && git pull dart-sdk/sdk/ > gclient getdep -r sdk/third_party/pkg/pub a3f8b2fd36ec432450caf907474a02023ef3e44e6.2 在依赖仓库中创建遴选并推送
pub/ > git checkout -b cherry-pick a3f8b2fd36ec432450caf907474a02023ef3e44e pub/ > git cherry-pick $commit-to-cherry-pick pub/ > git push -u origin cherry_pick:cherry_pick pub/ > git rev-parse HEAD 6d1857c84cfb8a014aefedaf2d453214bf5ddb96 # <-- 这就是我们要移动到的修订版本推送后需要等待片刻,让变更镜像到 dart.googlesource.com。
6.3 将遴选提交合并进受保护分支
必须确保依赖上的遴选提交被合并进受保护分支(这里指main),否则存在被垃圾回收(GC)的风险。下面的脚本可以创建这样的合并:
#!/bin/bash BRANCH="<name of branch to merge>" REPO="<name of repository>" # Defaults that may need to be changed. TARGET_BRANCH="main" # sometimes repositories use a different default branch. ORG="dart-lang" # most dependencies are in dart-lang, but not all. REMOTE=origin # use upstream if that is the target repo's remote. # Clone the repo if you don't already have a clone. gh repo clone "$ORG/$REPO" # Switch to the repo's directory. cd "$REPO" # Fetch and create a branch tracking the target branch. git fetch "$REMOTE" git switch -c "merge-$BRANCH" "$REMOTE/$TARGET_BRANCH" # Create a merge commit. git merge -sours "$REMOTE/$BRANCH" gh pr create为这个合并创建 PR 时,务必选择"merge"(合并提交)而不是 "squash"(压缩合并)——必要时可能需要临时调整仓库设置才能做到。
6.4 在 SDK 检出中提升 DEPS 版本并上传 CL
回到 SDK 检出目录,使用tools/manage_deps.dart创建一个 bump 提交和一个将发布通道移动到新遴选提交(注意是遴选提交而非合并提交)的 CL:
dart-sdk/sdk/ > tools/manage_deps.dart bump third_party/pkg/pub --target=6d1857c84cfb8a014aefedaf2d453214bf5ddb96然后将该 CL 改为相对于发布通道:
dart-sdk/sdk/ > git branch --set-upstream-to=origin/beta dart-sdk/sdk/ > git cl upload这个 CL 即可直接用于上文所述的 cherry-pick 流程。
源码侧证:tools/manage_deps.dart 的实现印证了上述流程:bump命令会先检查 git 工作区是否干净、创建bump_<dependency>分支、通过gclient getdep -r sdk/<dependency>找到当前修订、再用gclient setdep -r 'sdk/<dependency>@<target>'更新 DEPS 中对应的依赖条目并同步依赖,最后创建带git log的提交并提示创建 CL。而 DEPS 中Var("dart_root") + "/third_party/pkg/pub"一栏正对应Var("dart_git") + "pub.git" + "@" + Var("pub_rev"),即每个依赖修订号最终以@revision形式固化在 DEPS 文件中。
七、常见注意事项与要点速查
| 环节 | 关键要求 |
|---|---|
| 适用范围 | 仅 bug 与回归修复;新功能等待下一版本 |
| 目标分支 | origin/beta或origin/stable,禁止直接落地 CL |
| 提交信息 | 首行加[beta]/[stable];Reviewed-on改名为Cherry-pick;删除Change-id/Commit-queue/Reviewed-by |
| 描述字段 | Issue description / What is the fix / Why cherry-pick / Risk / Issue link(s) |
| CHANGELOG | stable 必须写,beta 不写;无小节则新增并递增 patch 号(不写日期);已发布小节不可改 |
| 豁免 | 对用户不可见的基础设施变更可用Changelog-Exempt: ... |
| 评审与提交 | 领域专家 + 团队负责人评审;commit queue 对比上一提交防回归;必要时可强制提交 |
| 依赖遴选 | 先在依赖仓库推送遴选,合并进其默认分支,再manage_deps.dart bump提升 SDK 依赖版本 |
| 版本号联动 | stable cherry-pick 递增 PATCH(见 tools/VERSION 注释规则) |
掌握上述流程后,无论是 SDK 自身代码的紧急修复,还是third_party依赖中的关键补丁,都能安全、合规地进入 beta/stable 热修复版本,第一时间交付给受影响的用户。
- 编程语言
- 编译器
- 语言运行时
- 标准库
- 开发工具
【免费下载链接】sdk
The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
相关推荐
rsuite-table源码解析:深入理解高性能表格组件的实现原理
rsuite table源码解析:深入理解高性能表格组件的实现原理 rsuite table是一个功能强大的React表格组件库,专为处理大规模数据而设计。作为
桌面应用富文本Flutter 构建发布渠道(build/release channels)全解析:master、beta、stable 的选择、切换与热修复流程
Flutter 构建发布渠道(build/release channels)全解析:master、beta、stable 的选择、切换与热修复流程 Flutte
跨平台移动开发前端UI组件桌面应用Realm Swift SDK 发布流程全指南:master 正式版、分支预发布与热修复补丁的完整发布手册
Realm Swift SDK 发布流程全指南:master 正式版、分支预发布与热修复补丁的完整发布手册 导读 本文以仓库 contrib/ReleasePr
数据库移动开发嵌入式数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考