4. Git仓库策略与分支模型

S32K3量产软件的版本治理,最先遇到的不是CI脚本怎么写,而是“代码放在哪里、分支怎么开、标签怎么打”。一个S32K3平台往往同时服务多个客户项目,每个项目又可能对应不同硬件版本(如EVB、A样、B样、量产板),并且共享MCAL、RTD、安全库、Bootloader等基础组件。如果仓库布局和分支模型没有提前设计,后期会出现“同一份代码在不同客户分支反复合并”“硬件版本差异靠宏开关堆叠”“量产标签无法追溯”等问题。本节从仓库布局、分支策略、标签规范三个层面给出可落地的方案。

一、仓库布局:平台仓 + 项目仓 + 交付仓

推荐采用“平台仓 + 项目仓 + 交付仓”的三层布局,而不是把所有项目塞进一个巨型仓库。平台仓(s32k3-platform)存放与客户无关的公共资产:MCAL配置模板、RTD驱动封装、OS抽象、诊断栈、安全库、构建脚本、CI流水线定义。项目仓(s32k3-customer-project)存放客户特定的应用逻辑、标定数据、客户诊断规范、项目级配置。交付仓(s32k3-delivery)存放经过验证的二进制、Hex、MAP、标定文件以及对应的版本清单,供生产、测试和客户交付使用。

平台仓与项目仓之间通过“版本化依赖”关联,而不是通过分支合并。平台仓每次发布一个平台基线(如 platform-v2.3.0),项目仓在 platform.lock 或 manifest.xml 中锁定该基线。这样,当平台仓修复一个MCAL缺陷时,只需发布新的平台基线,各项目按需升级,避免跨项目分支互相污染。对于必须共享的硬件抽象层(HAL),可以单独拆成 s32k3-hal 仓,由平台仓和项目仓共同依赖。

S32K3 三层仓库布局与依赖关系 平台仓 s32k3-platform • MCAL / RTD 配置模板 • OS 抽象 / 诊断栈 • 安全库 / Bootloader 框架 • 构建脚本 / CI 流水线 • 发布平台基线 platform-vX.Y.Z 硬件抽象仓 s32k3-hal • 板级初始化 / 时钟树 • 引脚复用 / 外设封装 • 硬件版本差异隔离 • 按硬件版本打标签 • 发布 hal-vX.Y.Z 项目仓 s32k3-cust-proj • 客户应用逻辑 • 标定数据 / 诊断规范 • 项目级配置 • platform.lock 锁定基线 • 发布项目版本 交付仓 s32k3-delivery • 已验证的 .hex / .bin / .map / .a2l • 版本清单 manifest.json(含平台基线、HAL版本、项目版本、硬件版本) • 每个交付包对应唯一标签,供生产与客户追溯 • 只读归档,禁止直接修改 平台基线 + HAL版本 + 项目版本 + 硬件版本 → 唯一交付标签

二、分支策略:主干开发 + 发布分支 + 项目分支

平台仓采用“主干开发 + 发布分支”模型。主干 main 始终保持可构建、可测试,所有新功能通过短生命周期特性分支合入。当平台达到一个稳定状态时,从 main 切出 release/platform-v2.3 发布分支,只接受缺陷修复,不再合入新功能。修复通过 cherry-pick 从 main 回移到发布分支,并递增补丁号。这样,项目仓可以稳定依赖 platform-v2.3.1,而不会被 main 上的新功能干扰。

项目仓采用“项目主干 + 客户发布分支”模型。项目主干 main 跟踪平台最新稳定基线,用于持续集成和早期验证;客户发布分支 release/customerA-bsample 用于冻结交付。硬件版本差异不通过分支隔离,而是通过HAL仓的标签和项目仓的配置选择来区分。例如,B样硬件使用 hal-v1.4.0,C样硬件使用 hal-v1.5.0,项目仓在 platform.lock 中显式指定,避免“同一分支兼容多硬件”的宏开关地狱。

三、标签规范:让每一次量产都可追溯

标签是版本治理的锚点。建议采用“三段式”标签:<仓类型>-<版本号>-<硬件/客户标识>。平台仓标签如 platform-v2.3.0;HAL仓标签如 hal-v1.4.0-bsample;项目仓标签如 proj-customerA-v1.2.0-bsample;交付仓标签如 delivery-customerA-v1.2.0-bsample-20250612。标签一旦推送,禁止删除或移动,确保任何一台量产件都能通过标签回溯到确切的源码、配置和工具链版本。

交付仓的 manifest.json 是追溯的核心,建议包含以下字段:项目名称、客户名称、硬件版本、平台基线标签、HAL标签、项目标签、编译器版本、RTD版本、构建时间、构建流水线编号、二进制SHA256。生产或客户反馈问题时,只需提供交付标签,即可在几分钟内还原完整构建环境。

建议在项目仓根目录放置 platform.lock,内容为YAML格式,明确锁定平台仓、HAL仓的标签和提交哈希。CI在构建前先校验锁文件与远程标签是否一致,不一致则直接失败,防止“本地能编、CI编不过”的漂移。

四、实操示例:一个客户项目的版本锁定

假设客户A的B样项目需要基于平台 platform-v2.3.1 和HAL hal-v1.4.0-bsample 构建。项目仓的 platform.lock 可以写成:

platform:
  repo: git@gitlab.example.com:s32k3/s32k3-platform.git
  tag: platform-v2.3.1
  commit: a1b2c3d4e5f6
hal:
  repo: git@gitlab.example.com:s32k3/s32k3-hal.git
  tag: hal-v1.4.0-bsample
  commit: 9f8e7d6c5b4a
project:
  name: customerA-bsample
  version: v1.2.0
toolchain:
  compiler: GCC 10.3.1
  rtd: 3.0.0

CI流水线在 build 阶段首先执行 git ls-remote --tags 校验标签存在且提交哈希匹配,然后拉取对应代码进行构建。构建成功后,产物上传到交付仓,并自动生成 manifest.json。如果后续需要为C样硬件构建,只需修改 platform.lock 中的HAL标签为 hal-v1.5.0-csample,提交后触发新的流水线,无需创建新分支或复制代码。

五、常见反模式与规避

反模式一:所有项目共用一个仓库、一个分支,靠 #ifdef CUSTOMER_A 区分。后果是代码耦合严重,一个客户的修改可能影响其他客户,CI无法独立验证。规避方式是拆分为独立项目仓,公共部分下沉到平台仓或HAL仓。

反模式二:用分支区分硬件版本,如 hw-bsample、hw-csample。后果是分支间合并冲突频繁,修复需要多次cherry-pick。规避方式是用HAL标签和配置选择硬件版本,保持项目分支单一。

反模式三:标签随意命名,如 test1、final、final2。后果是无法自动化解析和追溯。规避方式是强制三段式标签,并在CI中加入标签格式校验,不符合规范的标签直接拒绝推送。

标签一旦用于量产交付,必须视为不可变对象。如果发现标签指向错误提交,正确做法是发布新的补丁标签(如 proj-customerA-v1.2.1-bsample),而不是删除或强推原标签。强推标签会导致已交付产物的追溯链断裂,是版本治理中的严重事故。

总结来说,S32K3多项目、多客户、多硬件版本的仓库治理,核心是“分层解耦、标签锁定、分支收敛”。平台仓和HAL仓提供稳定基线,项目仓按客户和项目独立演进,交付仓以不可变标签归档产物。分支只用于开发节奏隔离,不用于硬件或客户隔离;硬件差异通过HAL标签和配置选择表达。这样,CI才能在每个项目上独立、可重复地构建和验证,量产追溯才有可靠依据。