4. Git仓库策略与分支模型
RH850量产软件的仓库策略,核心矛盾在于:功能安全要求可追溯、可复现的发布基线,而嵌入式团队又必须持续接收MCAL更新、硬件改版和客户需求变更。分支模型选错,轻则合并冲突频发,重则导致某次量产固件无法从Git历史中精确重建。本节不讨论抽象优劣,而是把三种主流模型放到RH850项目的真实约束下做取舍。
三种模型的本质差异
主干开发(Trunk-Based Development)要求所有开发者频繁向main分支提交小粒度变更,通常配合特性开关(Feature Flag)和短生命周期分支(存活不超过1~2天)。它的优势是集成风险前置、历史线性清晰;代价是对自动化测试覆盖率和代码评审纪律要求极高。
Git Flow使用main、develop、feature、release、hotfix五类分支,发布分支长期存在。它适合有明确版本窗口、需要并行维护多个量产版本的项目,但分支合并路径复杂,在RH850这种需要频繁同步MCAL补丁的场景下,容易产生“补丁在develop修了、release没同步”的经典问题。
GitHub Flow只有main加短生命周期feature分支,通过Pull Request合并,强调持续部署。它比Git Flow轻,但缺少release分支这一层,对需要冻结发布候选版本的量产项目需要额外约定。
RH850项目的取舍依据
RH850量产项目通常同时存在三类工作流:MCAL/驱动同步(外部输入,节奏不可控)、应用功能开发(内部迭代)、量产版本维护(客户现场问题修复)。判断用哪种模型,看三个问题:
- 是否需要同时维护两个以上量产版本? 若客户A停留在V1.2、客户B已到V2.0,且V1.2仍需修bug,Git Flow的release分支或主干开发的release tag+cherry-pick更合适。
- MCAL更新频率是否高于应用发布频率? 若MCAL每两周更新一次,而应用每季度发布一次,主干开发配合每日CI能最快暴露集成问题。
- 团队是否有专职发布经理? Git Flow的release分支需要有人负责冻结、测试、合回,小团队往往没有这个角色。
实践中,多数RH850量产团队采用“主干开发+发布标签”的混合模型:main分支保持可构建,每次量产发布打tag(如v1.2.0-rh850),需要维护旧版本时从tag拉出release/v1.2分支,仅接受cherry-pick的修复提交。这样既保留了主干开发的集成效率,又满足了量产版本可追溯的要求。
分支保护规则
无论选哪种模型,main分支必须设置保护规则。以下是一份可直接参考的配置示例(以GitLab为例,GitHub/Bitbucket字段名不同但语义一致):
# main分支保护规则(示例)
protected_branches:
- name: main
push_access_level: no_one # 禁止直接push
merge_access_level: maintainer # 仅维护者可合并
allow_force_push: false
code_owner_approval_required: true # 需CODEOWNERS批准
required_approvals: 2 # 至少2人评审
dismiss_stale_approvals: true # 新提交后旧批准失效
require_status_checks:
- build_rh850 # 编译通过
- unit_test # 单元测试
- static_analysis # MISRA检查
- can_bus_test # CAN通信回归
对RH850项目,CODEOWNERS应至少覆盖:/mcal/由底层驱动负责人审批,/safety/由功能安全工程师审批,/config/由集成负责人审批。这样避免“一个应用开发者误改MCAL配置导致量产件无法启动”的事故。
合并策略
合并策略直接影响历史可读性和回滚能力。三种常用方式:
| 策略 | 命令 | 历史形态 | RH850适用场景 |
|---|---|---|---|
| Merge Commit | git merge --no-ff | 保留分支拓扑 | release分支合回main,需保留发布节点 |
| Squash Merge | git merge --squash | 单提交线性 | feature分支合并,一个功能一个提交 |
| Rebase | git rebase main | 完全线性 | 本地整理提交,禁止对已推送分支rebase |
推荐约定:feature分支用Squash Merge进main,保证main上每个提交对应一个完整功能或修复;release分支用Merge Commit合回main,保留发布边界;禁止对main和release分支执行rebase,因为其他开发者可能已基于这些分支工作。
冲突解决
RH850项目的冲突高发区集中在:.ld链接脚本、.arxml配置、CanIf_Cfg.c等生成文件、以及Makefile。处理原则:
- 生成文件不手工合并。若
CanIf_Cfg.c冲突,应回到配置工具重新生成,而不是在Git里逐行解决。将生成文件标记为merge=ours或纳入.gitattributes的binary处理。 - 链接脚本冲突按段处理。先确认双方新增的section是否可共存,再决定合并顺序。例如一方新增
.safety_ram,另一方调整.stack大小,两者可同时保留。 - 配置冲突用三方工具。
git mergetool配合Beyond Compare或KDiff3,逐块确认,避免遗漏MCAL版本相关的宏定义。
can_bus_test和flash_write_test,确认链接脚本和启动代码未被破坏。
最后给出一份可直接使用的分支命名与生命周期约定:
# 分支命名规范(示例)
feature/RH850-1234-canfd-driver # 功能分支,关联需求号
bugfix/RH850-5678-can-timeout # 缺陷修复
release/v1.2.0 # 发布分支,从main拉出
hotfix/v1.2.1 # 紧急修复,从release拉出
# 生命周期
feature/* → 合并后删除,存活≤5个工作日
release/* → 发布后保留,仅接受cherry-pick
hotfix/* → 修复验证后合并回main和release,删除
这套约定配合分支保护规则,能让RH850量产软件在“快速集成”和“可追溯发布”之间取得平衡。选择模型时不必追求理论最优,而应匹配团队规模、MCAL更新节奏和客户版本数量这三个现实约束。