3. 集成测试核心概念

嵌入式项目的版本控制,说白了就是给代码上「保险」。我见过太多团队,代码乱成一锅粥,最后连哪个版本能跑都不知道。今天咱们聊聊分支策略——Git Flow 和 Trunk Based,到底怎么选。

两种主流分支模型

先看个对比表格,心里有个底:

特性 Git Flow Trunk Based
分支数量 多(develop、feature、release、hotfix) 少(主分支 + 短期特性分支)
发布频率 低(周/月级) 高(天/小时级)
适合场景 硬件依赖强、发布周期固定 CI/CD 成熟、快速迭代
合并复杂度 高(长期分支容易冲突) 低(频繁合并,冲突少)
嵌入式适配度 ★★★★☆ ★★★☆☆

Git Flow:嵌入式项目的「老黄牛」

我个人习惯在固件版本迭代慢、硬件平台固定的项目里用 Git Flow。为什么?因为嵌入式开发有个痛点——硬件依赖。

你想想看,一个功能写好了,但硬件还没回来。这时候 feature 分支就派上用场了。我在一个车载项目里遇到过:MCU 换型号,底层驱动全部重写。如果用 Trunk Based,主分支天天坏,CI 根本跑不过。Git Flow 的 develop 分支给了我们缓冲期,等硬件稳定了再合并。

核心分支结构:

  • master:只放发布过的版本,每个 commit 对应一个 Release
  • develop:日常开发集散地,所有 feature 往这合
  • feature/*:新功能开发,从 develop 拉,合回 develop
  • release/*:发布前准备,修 bug、改文档,合回 master 和 develop
  • hotfix/*:线上紧急修复,从 master 拉,合回 master 和 develop

Trunk Based:CI/CD 的「加速器」

如果你的 CI/CD 流水线足够成熟,测试覆盖率够高,Trunk Based 会让你爽到飞起。我建议在原型验证阶段用这个模式——代码改得快,反馈也快。

Trunk Based 的核心就一句话:所有人往主干合,每天至少合一次。听起来简单,做起来难。我曾经在一个 IoT 项目里强推 Trunk Based,结果第一天 CI 就红了 8 次。为什么?因为嵌入式代码的编译时间长,单元测试跑得慢。

我的经验:Trunk Based 要想在嵌入式项目里落地,必须做到三点:

  1. 编译时间控制在 5 分钟内(用增量编译 + 分布式构建)
  2. 单元测试覆盖核心逻辑(驱动层用模拟器跑)
  3. 特性开关(Feature Toggle)要到位,没完成的功能直接关掉

怎么选?看这张流程图

嵌入式项目分支策略选择流程 项目启动 硬件平台是否稳定? 是 否 Trunk Based Git Flow CI/CD 是否成熟? 是 否 Trunk Based Git Flow 提示:硬件稳定 + CI 成熟 → Trunk Based;否则 → Git Flow 混合模式也常见:核心固件用 Git Flow,应用层用 Trunk Based

代码审查与门禁机制

分支策略定好了,代码怎么进来?靠审查和门禁。我见过最惨的一次:有人把调试用的 printf 直接提交到 master,结果产线刷了固件,控制台疯狂打印日志,把 Flash 写坏了。

从那以后,我定了几条铁律:

门禁机制清单(MR 必须通过):

  • 静态检查:MISRA-C 规则扫描,违规数必须为 0
  • 编译检查:所有目标平台(ARM、RISC-V、Xtensa)全部通过
  • 单元测试:新增代码覆盖率 ≥ 80%,核心模块 ≥ 90%
  • 集成测试:至少通过冒烟测试用例集
  • 代码审查:至少 2 个 Reviewer 批准,且 Reviewer 不能是作者

代码审查我建议用「小步提交」原则。每次 MR 不要超过 200 行,超过就拆。为什么?因为人一次看 200 行代码还能保持清醒,看 2000 行就只想点「批准」了。

我的审查习惯:

  1. 先看测试代码,再看业务代码——测试写得好,代码一般不会差
  2. 重点关注边界条件、中断上下文、内存操作
  3. 遇到「魔法数字」必须问清楚,不能放过
  4. Review 评论用「建议」语气,别用「你错了」

标签与 Release 管理

标签是版本控制的「锚点」。没有标签的仓库,就像没有路标的迷宫。我建议用语义化版本号:

vMAJOR.MINOR.PATCH-预发布标识+构建元数据

示例:
v2.1.0-rc.1+build20240315
v2.0.0
v1.3.2-hotfix.1

嵌入式项目里,标签还要带上硬件信息:

标签格式 含义 示例
v{major}.{minor}.{patch} 正式发布 v3.1.0
v{major}.{minor}.{patch}-rc.{n} 候选版本 v3.1.0-rc.2
v{major}.{minor}.{patch}-{hw} 指定硬件平台 v3.1.0-stm32f4
v{major}.{minor}.{patch}-hotfix.{n} 紧急修复 v3.0.1-hotfix.1

Release 管理我推荐用 GitLab Release 或 GitHub Release,配合 CI 自动生成 changelog。每次打标签时,CI 自动做三件事:

  1. 编译所有目标固件
  2. 运行全量回归测试
  3. 生成 Release Notes(从 commit message 提取)

我曾经踩过的坑:

  • 标签打了但没推远端,同事拉不到,白忙活半天
  • Release Notes 用手写,漏了关键变更,产线刷错固件
  • hotfix 标签没合并回 develop,下次发布又把 bug 带出来了

现在我的流程是:标签必须由 CI 自动打,人工只负责确认版本号。Release Notes 从 commit 自动生成,再人工审核补充。

嗯,版本控制这件事,说难不难,说简单也不简单。关键是形成习惯,让流程成为肌肉记忆。下次咱们聊聊 CI 流水线怎么搭,那才是真正让分支策略发挥价值的地方。