Flutter 构建发布渠道(build/release channels)全解析:master、beta、stable 的选择、切换与热修复流程
Flutter 通过 master、beta、stable 三个官方 Git 分支(即「渠道 channel」)向开发者分发不同稳定性等级的 SDK 构建。本文以 Flutter-Build-release-channels.md 为核心,结合 Flutter 工具链源码,系统讲解各渠道的定位、发版节奏、版本号差异、切换与升级命令的底层实现,以及特定缺陷能否进入 hotfix 与 cherry-pick 的判断依据。读完你将能根据自身场景(日常开发、生产发布、源码贡献)正确选渠道,熟练操作 flutter channel / flutter upgrade,并掌握官方 hotfix 流程与自己动手 cherry-pick 的边界。
渠道总览:三个官方分支与稳定性递增
Flutter 官方维护的渠道按稳定性递增排列为:master → beta → stable。这一顺序并非文档中的随意描述,而是固化在工具链源码中。在 packages/flutter_tools/lib/src/version.dart 内可以找到渠道的定义:
/// The names of each channel/branch in order of increasing stability.
enum Channel { master, main, beta, stable }
// Beware: Keep order in accordance with stability
const kOfficialChannels = <String>{'master', 'main', 'beta', 'stable'};
const kChannelDescriptions = <String, String>{
'master': 'latest development branch, for contributors',
'main': 'latest development branch, follows master channel',
'beta': 'updated monthly, recommended for experienced users',
'stable': 'updated quarterly, for new users and for production app releases',
};
const kDevelopmentChannels = <String>{'master', 'main'};
几点值得注意:
kOfficialChannels中同时包含master与main,main被定义为「跟随 master 渠道的最新开发分支」。官方文档中记录的「计划将master重命名为main」的工作,在当前仓库源码中已落地为两者并存的渠道结构。- 渠道本质上就是 Flutter 仓库的 Git 远程分支(
git branch -r可列出),切换渠道 = 切换 SDK 仓库所在分支,这也是flutter upgrade可以直接复用 Git 工具的原因。 - 工具链在判定「本地安装是否过旧」时会按渠道给出不同宽限期(见后文「过期提醒机制」),同样证明各渠道发版节奏不同。
master(亦称 main):每日更新的尖端开发分支
master 指向 Flutter 仓库的 tip-of-tree,即最前沿的构建版本。其特点包括:
- 通常可运行,但偶有损坏:Flutter 团队在允许补丁合入该分支前,并不会跑完全部测试套件,因此官方文档明确不推荐普通用户使用
master,除非你是 Flutter 的贡献者。 - API 文档随时段更新:
master分支最近一次提交的 API 文档会实时暂存到官方主站对应区域;stable的文档通常正确,但可能缺少新特性,而master的文档虽最新、却可能提及尚未进入beta的特性。 - 插件持续适配:Flutter 团队的官方插件与 packages 会定期针对
master分支进行回归测试,以保证上游改动不会长期破坏生态。
从工具链角度,master/main 属于「开发渠道」,工具在两类场景下对它们有特殊对待:
- 版本计算需要拉取远程 tag:在 version.dart 的
fetchTagsAndGetVersion()中,master和main需要git fetch --tags后相对上游 tag 计算版本号;而beta/stable发布时本身恰好在某个 tag 上,无需此步骤。 - 升级后的强提示:执行
flutter upgrade切到master/main后,工具会打印醒目的「此渠道面向 Flutter 贡献者,测试不如 beta/stable 充分,正常使用建议改用 beta 渠道」的警告(见 upgrade.dart)。
如果你的诉求是「尝鲜最新特性」,官方推荐的是
beta而非master。
beta:经完整测试的最新候选,月更一次
beta 是 Flutter 目前最新且经过高强度测试的版本,文档中的表述为「如果你想使用最新最好的,beta 是正确的选择」。它之所以可靠,是因为:
- 通过了全部公开测试;已被 Google 内部使用 Flutter 的产品测试套件验证过;还经过社区贡献的私有测试套件(flutter/tests 组织下维护)校验。
- 发版节奏固定:团队在月初(通常为第一个周三)从
master切出新的 beta 分支,同时为 Dart、Engine、Framework 分别建立分支,随后用数周时间「稳定化」这些分支——稳定化的主要手段是接受针对高影响问题的 cherry-pick 请求。 - 修复到达平均约两周:一个修复合入仓库(
master渠道)后,平均约两周就能进入beta分支。 - 季度性晋升:每季度有一次,beta 分支会继续演进为下一个
stable分支(详见下节)。
beta 的 API 文档策略
官方不为 beta 单独托管 API 文档。开发者只能二选一:
- 查阅
stable的文档(通常正确,但可能缺新特性); - 查阅
master的文档(更新,但可能包含 beta 尚未拥有的功能)。
当 beta 处于「接近下一个 stable」的阶段时,官方也鼓励开发者主动试用该 beta,以便提前暴露回归问题。
stable:季度更新,面向新用户与生产发布
stable 的晋升规则大致是「每三个 beta 中有一个被提升为 stable」,因此它与 beta 本质上内容相同,只是更新频率更低(约季度更新一次)。官方的明确建议是:
- 新用户优先使用
stable; - 生产 App 发布应使用
stable。
stable 的配套保障包括:
- 高严重度、高影响或安全问题会触发 hotfix 发布,流程与
beta一致,同样走 cherry-pick 流程。 - Flutter 官方插件与 packages 会持续针对最新
stable分支做测试(对比master的「定期」)。 - 版本号形态为规整的
X.Y.Z。在 version.dart 的版本解析逻辑中,工具会优先匹配^\d+\.\d+\.\d+$形态的 tag 作为 stable 版本,其余-pre后缀或git describe输出则被归为开发版本。
如何切换渠道:flutter channel 与 flutter upgrade
查看当前所处渠道:
$ flutter channel
Flutter channels:
* stable
beta
master
行首的 * 表示当前所在渠道。切换渠道分两步:
$ flutter channel beta # 切换到 beta 渠道
$ flutter upgrade # 拉取该渠道最新构建
需要说明的是,flutter channel 的实际能力不止「官方三渠道」这么简单,命令本身由 channel.dart 实现,其内部逻辑揭示了若干实用细节:
flutter channel(无参数)列出渠道:命令执行git branch -r读取远程分支,并只展示kOfficialChannels中的成员;若当前处于自定义分支(非官方渠道),列表底部会额外输出* <分支名>与Currently not on an official channel.提示(源码见 channel.dart,输出格式有对应单元测试覆盖于 channel_test.dart)。-a/--all:在列表中额外展示所有可用分支(含本地分支与远程其他分支),默认隐藏。-f/--force:强制切换,会丢弃本地未提交改动(内部执行git checkout -f)。--cache-artifacts:切换完成后自动执行等效于flutter precache --all-platforms的二进制产物预下载,默认开启。- 内部执行序列:切换时工具依次执行
git fetch→git show-ref --verify判断本地分支是否存在 → 已存在则git checkout <branch>,否则git checkout --track -b <branch> origin/<branch>;随后删除版本检查时间戳,避免上个渠道的过期信息残留(channel.dart)。 - 废弃渠道自动迁移:源码中维护了一张旧分支映射表
const kObsoleteBranches = <String, String>{'dev': 'beta'}。dev渠道于 2021 年被弃用并迁移至beta;切换时若命中旧渠道名,工具会提示改用替代渠道,flutter upgrade遇到废弃渠道时也会自动_checkout到对应新渠道(version.dart 与 channel.dart)。
从源码看 flutter upgrade 的两阶段执行
flutter upgrade 命令的实现位于 upgrade.dart,它的执行被设计为两阶段接力,原因很直观:升级过程会替换正在运行的 Flutter 工具本身,因此「拉取新代码」必须由旧版本完成,而「换新后的收尾工作」则交给新版本自身以 --continue 参数重新进入。
第一阶段(旧版本执行,UpgradePhase.firstHalf):
git fetch --tags并解析上游最新提交,构造远端版本对象(fetchLatestVersion,upgrade.dart);- 若本地已是最新且 tag 不比上游旧,直接提示
Flutter is already up to date on channel ...返回; - 检查本地是否有未提交改动(
hasUncommittedChanges)——若改动会丢失则中止,除非加--force。值得注意的细节是:非 stable 渠道会忽略 pubspec.lock 的改动(upgrade.dart); - 通过
ChannelCommand.upgradeChannel处理废弃渠道自动迁移; - 执行
git reset --hard <newRevision>(attemptReset),删除版本缓存文件; - 用新代码重新调用
bin/flutter upgrade --continue --continue-started-at <ISO8601时间戳> --no-version-check。
第二阶段(新版本执行,UpgradePhase.secondHalf):
- 运行
flutter precache下载并更新 Engine 等二进制产物(precacheArtifacts); - 对当前项目执行
pub get(updatePackages); - 自动运行
flutter doctor,检测升级后新增的依赖要求。
此外还有几个实用 flag:--verify-only 只检测不下载(并会打印当前版本与最新版本的 revision 对比);--force 丢弃本地改动强制执行。
过期提醒机制:各渠道的「新鲜度」宽限期
如果你没有主动 upgrade,Flutter 工具会在执行命令时静默检查版本新鲜度并给出升级提示。这个逻辑集中在 checkFlutterVersionFreshness()(version.dart 起)。工具对该功能做了多重克制设计,源码注释交代得十分清楚:
- 仅对官方渠道生效:不在
kOfficialChannels内(如用户自己的分支)直接跳过检查; - 按渠道定义宽限期
versionAgeConsideredUpToDate(channel)(version.dart):stable:六个月(约半年一次大版本);beta:八周(覆盖约每月一次的 beta 发布);- 其余(master/main):三周。
- 只有当「远端确实有新版本」或「本地安装已超出宽限期」时才提示;并且会记录上次警告时间,避免打扰故意不升级的用户。
某个缺陷能否进入 hotfix 发布?
官方明确回答:视缺陷严重程度而定,是可能的。 完整判断与申请流程见 Flutter Cherry-pick 流程文档。核心结论速览:
- 背景原则:beta/stable 发布后以稳定性为最高目标,仅接受高影响、高严重度的修复(含安全修复);新特性一律不进入 cherry-pick,只能等下一个正式版本。
- 自动申请:在合入
master的 PR 上打上cp: beta或cp: stable标签,约 30 秒后若自动 cherry-pick 无冲突,会生成新的 cherry-pick PR 并邮件通知;失败则需走手工流程。 - 手工申请:向对应的候选分支(形如
flutter-X.XX-candidate.X)提交 PR,标题以[beta]或[stable]开头,并按模板填写受影响用户、影响描述、规避方案、风险、测试覆盖、验证步骤六项,再加cp: review标签等待发布工程团队指派评审。 - 典型生命周期:
cp:标签 → 评审专家审批 → 打上merge-to-beta/merge-to-stable标签 → 合入并在下一个发布周期随版本发布。 - 优先级策略:若某 stable 刚发布、多数开发者尚未迁移,官方会优先回移修复到该 stable;在稳定版收尾的几周内,则可能只向
beta发 hotfix。
等不及时,自己动手 cherry-pick
如果你非常需要某个已合入 flutter/flutter 的补丁,而它又因为各种原因无法进入官方 hotfix,文档给出了一条自给自足的路径:Flutter 本身就是以 Git 仓库形式分发的,Git 的全部能力都对你开放——完全可以在本地基于目标版本自己建分支并 cherry-pick 想要的 commit。
但请注意适用边界(这也是文档特别提醒的):
- 该方案只对 flutter/flutter 仓库内的修复 有效;
- 若补丁来自 flutter/engine 仓库或 Dart、Skia 等依赖,官方不提供打包好的中间产物,自行应用将意味着要自建 Engine;对绝大多数人而言「等待下一个 beta」是更现实的选择——毕竟平均每两周就有一个新 beta。
渠道选择速查
| 场景 | 推荐渠道 | 备注 |
|---|---|---|
| 新用户、零基础入门 | stable |
文档最完善、版本号规整 |
| 生产 App 发布 | stable |
官方唯一推荐的生产渠道 |
| 想用最新且经完整测试的特性 | beta |
月更、有 Google 内部与社区测试背书 |
| 贡献源码、需要对照 tip-of-tree | master / main |
不对全量测试负责,工具会有升级警告 |
| 有高优缺陷亟需修复 | beta/stable + cherry-pick | 走 cp: 标签或手工流程,见 Cherry-pick 流程 |
延伸阅读
- Flutter Cherry-pick 流程:hotfix 与补丁回溯的完整审批规范;
- CONTRIBUTING.md:面向 master/main 渠道使用者的贡献指南;
- channel.dart:
flutter channel命令完整实现; - upgrade.dart:
flutter upgrade两阶段升级实现; - version.dart:渠道常量、版本解析与过期判断逻辑;
- channel_test.dart:渠道列出/切换行为的单元测试样例。
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
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