分支策略:Git Flow、GitHub Flow、Trunk Based Development,哪种适合嵌入式项目?

说实话,这个问题我几乎每次培训都会被问到。

做嵌入式开发的兄弟,跟纯软件团队不一样。我们手里有硬件,有RTOS,有驱动,还有一堆编译工具链的坑。选分支策略,不能光看网上那些「最佳实践」——得看你的项目到底长什么样。

先聊聊三种主流策略

简单过一下,免得有人不熟悉。

Git Flow

经典中的经典。有 masterdevelopfeaturereleasehotfix 五类分支。流程严谨,适合有固定发布周期的项目。

优点:结构清晰,责任分明。谁在开发新功能,谁在修紧急bug,一目了然。

缺点:分支多,合并频繁。嵌入式项目如果硬件还在改版,光合并就能让你崩溃。

GitHub Flow

极简派。只有一个 main 分支,所有开发从 main 拉出 feature 分支,做完提PR,合并回 main,立刻部署。

优点:简单,快。适合持续部署的互联网项目。

缺点:对嵌入式来说,太激进了。你想想看,固件烧进去出了问题,可不是回滚个版本就能解决的——硬件可能已经报废了。

Trunk Based Development

主干开发。所有开发者直接往 trunk(或 main)提交小改动,频繁集成。分支存活时间通常不超过一天。

优点:冲突少,集成快。适合CI/CD成熟度高的团队。

缺点:对代码质量和自动化测试要求极高。嵌入式项目里,编译一次可能就要十分钟,跑个单元测试还得接硬件——你确定能承受这种频率?

嵌入式项目的特殊性

我个人习惯,先列几个嵌入式项目跟纯软件项目不一样的地方:

  • 硬件依赖:代码跑在真实硬件上,不是所有bug都能在模拟器里复现。
  • 编译慢:交叉编译链,加上各种宏定义、条件编译,一次完整构建可能半小时。
  • 发布周期固定:很多嵌入式产品是按季度或半年发版的,不是每天发。
  • 硬件版本并行:同一个项目,可能同时维护V1.0、V1.1、V2.0三个硬件版本。
  • 测试成本高:自动化测试覆盖率低,很多测试得靠人工拿着示波器测。

嗯,这里要注意——这些特殊性直接决定了哪种分支策略更合适。

我的建议:嵌入式项目首选「改良版Git Flow」

为什么不是GitHub Flow?

我在项目中遇到过,团队刚开始用GitHub Flow,觉得简单。结果有一次,硬件改版导致驱动接口全变了,所有feature分支都得重改。因为没有 develop 分支做缓冲,main 直接崩了三天。那三天,测试组的人天天来找我,说「固件烧进去就死机」。

为什么不是Trunk Based Development?

说实话,如果你的团队能做到每次提交都跑完完整的硬件在环测试,那Trunk Based Development确实香。但现实是,大多数嵌入式团队连自动化编译都没跑通。我曾经在一个项目里试过Trunk,结果每天下午四点,大家都不敢提交代码——因为一提交,CI就炸,一炸就是半小时。

所以,我推荐的是「改良版Git Flow」。

改良版Git Flow长什么样?

核心思想:保留Git Flow的结构,但砍掉不必要的分支。

分支 用途 嵌入式场景建议
master 发布版本 只合并经过完整测试的release分支
develop 日常开发集成分支 必须保留,作为缓冲
feature/* 新功能开发 从develop拉出,开发完合并回develop
release/* 发布准备 从develop拉出,只修bug,不添新功能
hotfix/* 紧急修复 从master拉出,修完同时合并回master和develop
hardware/* 硬件版本适配 新增分支,用于管理不同硬件版本的代码差异

关键点:嵌入式项目一定要加 hardware/* 分支。这是我踩过坑之后加上的。以前没有这个分支,硬件版本切换全靠宏定义,结果代码里到处都是 #ifdef HW_V1,维护起来想死。

具体怎么操作?

举个例子。假设我们正在开发一款剃须刀,硬件版本是V2.0。

# 1. 从develop拉出feature分支
git checkout develop
git checkout -b feature/blade-motor-control

# 2. 开发完成,合并回develop
git checkout develop
git merge feature/blade-motor-control

# 3. 准备发布V2.0.1
git checkout -b release/v2.0.1

# 4. 在release分支上只修bug
# 修完bug后,合并到master和develop
git checkout master
git merge release/v2.0.1
git tag v2.0.1

git checkout develop
git merge release/v2.0.1

# 5. 如果发现紧急bug
git checkout master
git checkout -b hotfix/crash-on-startup
# 修完
git checkout master
git merge hotfix/crash-on-startup
git tag v2.0.2

git checkout develop
git merge hotfix/crash-on-startup

小技巧:我习惯在 release/* 分支上只做bug fix,不做功能开发。这样release分支的代码质量可控,测试组也只需要关注这一份代码。

避坑指南

我曾经犯过一个错误——在 develop 分支上直接修bug。结果修到一半,发现这个bug跟某个feature分支的代码冲突。最后花了半天时间解冲突,还引入了新bug。

后来我定了个规矩:所有改动,不管大小,都必须走分支。哪怕只是改一个宏定义的值,也要从develop拉个分支出来改。

还有一个坑:不要频繁合并master到develop。嵌入式项目里,master上的hotfix可能跟develop上的新功能有冲突。我建议只在release分支准备发布时,才把master上的hotfix合并到develop。

警告:如果你的项目使用了Git LFS管理二进制文件(比如固件镜像、硬件原理图),一定要在分支策略里考虑LFS的存储成本。每个分支都会保存一份LFS文件的副本,分支多了,存储空间会爆炸。

什么时候可以考虑其他策略?

也不是说Git Flow就是唯一答案。我见过一些场景,其他策略反而更合适:

  • 小团队(3人以下)做原型验证:用GitHub Flow就够了。分支多了反而增加沟通成本。
  • 自动化测试覆盖率超过80%的成熟团队:可以尝试Trunk Based Development。但前提是,你的CI能在10分钟内完成编译+测试。
  • 纯固件开发,没有硬件版本并行:可以简化分支结构,去掉 hardware/* 分支。

但说实话,我做了十年嵌入式,见过的大多数项目,还是改良版Git Flow最稳。

总结一下

选分支策略,不是选「最好的」,而是选「最适合你团队当前状态的」。

嵌入式项目有它的特殊性——硬件依赖、编译慢、测试成本高。这些因素决定了我们不能照搬互联网团队的做法。

我个人习惯,先跑通改良版Git Flow,等团队成熟了,再考虑简化。别一上来就追求「极简」,那往往是给自己挖坑。

嗯,今天就聊到这儿。下一章我们讲讲版本号怎么定——别小看这个,我见过因为版本号乱标,导致产线烧错固件的事故。

专注资料整理