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的合并策略应当是“以工具为准,不以文本为准”。推荐流程如下:
- 在分支上修改ARXML后,先提交到各自分支,不急于合并。
- 合并前,由配置负责人确定“基线分支”,将两个分支的ARXML分别导出为工具可识别的差异报告。
- 在Vector工具中打开基线工程,手工或脚本化地应用另一分支的变更,而不是直接让Git合并XML文本。
- 合并完成后,用工具执行一次“一致性检查”,确认无悬空引用、无重复短名称。
- 将工具导出的最终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+生成代码+工具版本记录。
四、生成代码的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和制品下载地址。
六、冲突解决的实际判断依据
当合并冲突发生时,按以下顺序判断处理方式:先看冲突文件类型,再看冲突位置,最后看是否可再生成。ARXML冲突走工具合并;生成代码冲突走再生成;标定数据冲突需人工确认哪个分支的标定值有效;二进制冲突直接选择一方或重新构建。无论哪种方式,合并后都必须执行一次完整的“ARXML加载 + 代码生成 + 编译”验证,确认没有语义级冲突残留。
把上述策略固化为团队规范后,ARXML的合并冲突率通常可以从每周数次降到每月一两次,且每次冲突都有明确的处理路径,而不是靠个人经验临时判断。