4. 配置版本控制策略

在Vector AUTOSAR工程中,版本控制策略的核心矛盾在于:ARXML是文本但结构复杂,生成代码是文本但可再生成,而编译产物、标定数据、诊断数据库等往往是二进制。如果对所有工件采用同一种Git管理方式,要么仓库膨胀到无法克隆,要么合并冲突频繁到无法交付。本节从工件分类出发,给出可落地的Git管理策略、分支模型、冲突解决方法和二进制取舍原则。

一、先分类:哪些工件该进Git,哪些不该

把工程工件按“是否可再生成”和“是否文本可合并”两个维度分类,是制定策略的第一步。以下分类表可直接作为团队规范的基础:

工件类型典型文件是否进Git管理方式
配置源文件.arxml、.dbc、.ldf是文本,需合并策略
生成代码Rte.c、Com_Cfg.c、*.h是(或按需)文本,标记为生成物
编译产物*.o、*.elf、*.hex否CI产物仓库或制品库
标定数据*.a2l、*.dcm、*.cdfx视情况文本可合并,二进制用LFS
诊断数据库*.odx、*.pdx视情况PDX为二进制,用LFS
工具工程*.dpa、*.project是文本,但常含绝对路径

判断原则很简单:能由ARXML和工具链重新生成的,原则上不进Git;不能重新生成或重新生成代价极高的,必须进Git。生成代码处于中间地带——它可再生成,但再生成需要特定工具版本和License,因此多数团队选择将其纳入Git,但用.gitattributes标记为linguist-generated,并在合并时优先采用“重新生成”而非手工合并。

二、ARXML的合并冲突:为什么不能直接merge

ARXML虽然是人可读的XML,但Vector工具导出的ARXML通常包含大量自动生成的UUID、短名称引用和顺序敏感的容器元素。两个分支各自新增一个SWC时,Git的文本合并可能成功,但结果在工具中打开会报“引用不一致”——因为UUID冲突或SHORT-NAME路径重复。更常见的是,同一ECU配置在两个分支被修改,合并后出现重复的ECUC-CONTAINER-VALUE。

因此,ARXML的合并策略应当是“以工具为准,不以文本为准”。推荐流程如下:

  1. 在分支上修改ARXML后,先提交到各自分支,不急于合并。
  2. 合并前,由配置负责人确定“基线分支”,将两个分支的ARXML分别导出为工具可识别的差异报告。
  3. 在Vector工具中打开基线工程,手工或脚本化地应用另一分支的变更,而不是直接让Git合并XML文本。
  4. 合并完成后,用工具执行一次“一致性检查”,确认无悬空引用、无重复短名称。
  5. 将工具导出的最终ARXML作为合并提交,提交信息中注明“由工具合并,非文本合并”。
不要依赖Git的默认merge策略处理ARXML。即使文本合并无冲突,也可能产生工具无法加载的语义冲突。建议在.gitattributes中对*.arxml设置merge=ours或自定义merge driver,强制走工具合并流程。

三、分支模型:主干保护与短生命周期分支

对于AUTOSAR配置工程,推荐采用“主干保护 + 短生命周期特性分支 + 发布标签”的模型,而不是长期存在的develop/release多分支并行。原因在于ARXML的合并成本高,分支存活时间越长,合并冲突越复杂。

具体做法:main分支始终保持可生成、可编译、可刷写状态;每个配置变更(如新增一个CAN信号、调整一个RTE端口)从main拉出feature/xxx分支,生命周期控制在3~5天;合并前必须通过CI的ARXML一致性检查和代码生成检查;发布时在main上打v1.2.0标签,标签对应完整的ARXML+生成代码+工具版本记录。

AUTOSAR配置工程分支模型与合并路径 main 基线 合并A 合并B v1.2.0 feature/can-signal ARXML变更 + 生成代码 feature/rte-port ARXML变更 + 生成代码 合并门禁 ARXML一致性检查 代码生成 + 编译 v1.2.0 main提交 特性分支A 特性分支B 合并门禁 发布标签

四、生成代码的Git管理:标记、忽略与再生成

生成代码是否入库,取决于团队的工具链成熟度。如果CI环境能稳定复现Vector工具的代码生成,建议生成代码不入库,只在CI中生成并打包;如果工具License受限或生成结果需要人工微调,则入库,但必须遵守三条规则:

  • 在.gitattributes中标记*.c linguist-generated=true,让代码审查工具折叠生成代码的diff。
  • 生成代码的提交必须与对应的ARXML提交在同一个commit中,禁止分开提交,否则无法追溯“哪版配置生成了哪版代码”。
  • 合并时,生成代码冲突优先选择“重新生成”而非手工解决。具体操作:git checkout --theirs或--ours后,重新运行生成器,再提交。
# .gitattributes 示例
*.arxml  merge=arxml-merge  -diff
*.c      linguist-generated=true
*.h      linguist-generated=true
*.a2l    linguist-generated=true
*.hex    binary
*.elf    binary
*.pdx    binary filter=lfs diff=lfs merge=lfs -text

五、二进制工件的取舍:LFS还是制品库

二进制工件分两类:小体积、需版本追溯的(如A2L、DCM、CDFX),和大体积、可再生成的(如ELF、HEX、PDX)。前者建议用Git LFS管理,保留版本历史;后者建议放入CI制品库(如Artifactory、Nexus),Git中只保留一个指向制品版本的元数据文件。

判断阈值可参考:单个文件超过5MB且每次构建都变化,就不应直接进Git。以某ECU项目为例,一个完整HEX约8MB,每天构建10次,一个月就会给Git仓库增加约2.4GB历史,克隆时间从秒级恶化到分钟级。改用制品库后,Git仓库只保留build-manifest.json,记录构建号、工具版本、ARXML commit hash和制品下载地址。

如果团队已经使用Git LFS,注意LFS的存储配额和带宽成本。对于HEX/ELF这类纯产物,制品库通常比LFS更经济,且支持保留策略和权限控制。

六、冲突解决的实际判断依据

当合并冲突发生时,按以下顺序判断处理方式:先看冲突文件类型,再看冲突位置,最后看是否可再生成。ARXML冲突走工具合并;生成代码冲突走再生成;标定数据冲突需人工确认哪个分支的标定值有效;二进制冲突直接选择一方或重新构建。无论哪种方式,合并后都必须执行一次完整的“ARXML加载 + 代码生成 + 编译”验证,确认没有语义级冲突残留。

把上述策略固化为团队规范后,ARXML的合并冲突率通常可以从每周数次降到每月一两次,且每次冲突都有明确的处理路径,而不是靠个人经验临时判断。