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项目三种分支模型对比 主干开发 main feat feat feat 短分支 ≤2天 特性开关控制 线性历史 适合:MCAL同步频繁 CI覆盖率高、评审快 Git Flow main develop feat feat feat release 五类分支并行 多版本维护 合并路径复杂 适合:多客户版本并行 需长期维护旧版本 GitHub Flow main PR PR main + 短分支 PR评审合并 无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 Commitgit merge --no-ff保留分支拓扑release分支合回main,需保留发布节点
Squash Mergegit merge --squash单提交线性feature分支合并,一个功能一个提交
Rebasegit rebase main完全线性本地整理提交,禁止对已推送分支rebase

推荐约定:feature分支用Squash Merge进main,保证main上每个提交对应一个完整功能或修复;release分支用Merge Commit合回main,保留发布边界;禁止对main和release分支执行rebase,因为其他开发者可能已基于这些分支工作。

冲突解决

RH850项目的冲突高发区集中在:.ld链接脚本、.arxml配置、CanIf_Cfg.c等生成文件、以及Makefile。处理原则:

  1. 生成文件不手工合并。若CanIf_Cfg.c冲突,应回到配置工具重新生成,而不是在Git里逐行解决。将生成文件标记为merge=ours或纳入.gitattributes的binary处理。
  2. 链接脚本冲突按段处理。先确认双方新增的section是否可共存,再决定合并顺序。例如一方新增.safety_ram,另一方调整.stack大小,两者可同时保留。
  3. 配置冲突用三方工具。git mergetool配合Beyond Compare或KDiff3,逐块确认,避免遗漏MCAL版本相关的宏定义。
冲突解决后,必须重新执行完整CI流水线,不能仅凭“编译通过”就合并。RH850项目建议在合并前跑一次can_bus_test和flash_write_test,确认链接脚本和启动代码未被破坏。
禁止在main分支上直接解决冲突并push。所有冲突解决必须在feature或release分支完成,经PR评审后合并。直接push会绕过分支保护,导致量产基线不可追溯。

最后给出一份可直接使用的分支命名与生命周期约定:

# 分支命名规范(示例)
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更新节奏和客户版本数量这三个现实约束。