3、Git工作流设计:GitFlow、Trunk-Based Development在嵌入式团队中的适配

聊到Git工作流,很多嵌入式团队其实挺纠结的。我见过不少团队,上来就照搬互联网公司的GitFlow,结果发现嵌入式项目里那套「热修复分支」、「发布分支」搞得人晕头转向。也见过一些团队,直接全员往master上推,结果固件编译到一半,发现有人把驱动库改坏了。

说白了,嵌入式开发有它的特殊性。硬件依赖、编译时间长、版本管理复杂,这些因素决定了我们不能简单套用别人的流程。今天我就结合自己的经验,聊聊GitFlow和Trunk-Based Development这两种主流工作流,在嵌入式团队里到底该怎么落地。

3.1 GitFlow:适合多版本维护的嵌入式项目

GitFlow这套模型,我最早是在2010年左右接触的。当时我们做车载娱乐系统,需要同时维护三个硬件平台的固件版本。GitFlow的分支策略,说白了就是「各管各的」——开发分支、发布分支、热修复分支,各司其职。

核心分支结构:

  • master:只存放已发布的稳定版本
  • develop:日常开发的主分支
  • feature/*:功能开发分支,从develop拉出
  • release/*:发布准备分支,从develop拉出
  • hotfix/*:紧急修复分支,从master拉出

我记得有一次,客户突然说某个批次的MCU有硬件bug,需要紧急打补丁。当时我们正在开发新功能,develop分支上已经有很多未完成的代码。幸好用了GitFlow,直接从master拉了一个hotfix分支,修完合并回去,前后不到两小时。你想想看,要是大家都在一条分支上开发,那会儿估计得手忙脚乱。

嵌入式团队适配要点

GitFlow在嵌入式团队里用,有几个地方需要特别注意:

  • 硬件依赖分支:我建议把硬件平台相关的代码单独拉分支。比如 feature/board-v2-driver,这样不同硬件版本的开发不会互相干扰。
  • 编译缓存管理:GitFlow分支多,每次切换分支都要重新编译。我的做法是,在CI脚本里加上ccache,把编译缓存按分支名隔离。这样切回来时,编译时间能缩短70%以上。
  • 发布分支的冻结期:嵌入式项目发布前,通常需要做大量的集成测试。release分支一旦拉出,就不要再往里加新功能了。我曾经吃过这个亏——在release分支上临时加了个功能,结果导致整个测试周期延长了两周。

我的小技巧: 在release分支上,只允许提交bug修复和文档更新。新功能?老老实实等下一个版本。

3.2 Trunk-Based Development:适合快速迭代的嵌入式项目

Trunk-Based Development,说白了就是「主干开发」。所有开发者都在一条主干分支上工作,通过短生命周期的特性分支来隔离风险。这套模式在互联网公司很流行,但在嵌入式团队里,我一开始是持怀疑态度的。

为什么?因为嵌入式项目编译一次可能要半小时甚至更久。如果大家都在主干上提交,万一有人提交了有问题的代码,整个团队都得等着修复。但后来我发现,只要配合好CI和特性开关,Trunk-Based Development其实非常适合嵌入式项目。

嵌入式团队适配要点

  • 特性开关(Feature Toggle):这是Trunk-Based Development在嵌入式项目里的核心。比如你正在开发一个新的传感器驱动,可以用一个宏来控制:
// 特性开关示例
#define FEATURE_NEW_SENSOR_ENABLED 0  // 0:关闭, 1:开启

void sensor_init(void) {
#if FEATURE_NEW_SENSOR_ENABLED
    // 新驱动代码
    new_sensor_init();
#else
    // 旧驱动代码
    old_sensor_init();
#endif
}

这样,即使新驱动还没写完,也不会影响主干上的其他代码。我习惯在CI脚本里加一个检查:如果特性开关是关闭的,那新代码必须通过编译,但可以不通过功能测试。这样既保证了主干稳定,又不会拖慢开发节奏。

  • 短生命周期分支:Trunk-Based Development要求特性分支的生命周期不超过两天。嵌入式项目里,这个时间可以放宽到三天。为什么?因为硬件调试有时候需要反复烧录、测试,一天内搞不定很正常。但超过三天,分支就会变得「太胖」,合并时容易出冲突。

注意: 特性分支超过三天还没合并?我建议你停下来,先合并一次,再继续开发。别等到最后一天才合并,那会儿冲突能让你崩溃。

3.3 两种工作流的对比与选型建议

说了这么多,到底该选哪个?我整理了一个对比表格,你可以参考一下:

维度 GitFlow Trunk-Based Development
分支数量 多(长期分支多) 少(主干+短期分支)
适合场景 多版本维护、硬件平台多 单版本快速迭代、团队小
编译压力 中等(分支切换频繁) 高(主干提交频繁)
冲突风险 低(分支隔离好) 高(需要频繁合并)
CI要求 中等 高(每次提交都要验证)
学习成本

我个人习惯这样选:

  • 如果你的团队在维护多个硬件版本(比如同时支持v1.0和v2.0的板子),或者产品需要长期支持(LTS),那GitFlow更合适。
  • 如果你的团队在做原型验证、快速迭代,或者只有一条产品线,那Trunk-Based Development效率更高。

3.4 避坑指南:嵌入式团队常见的Git工作流问题

这些年我踩过不少坑,挑几个典型的说说:

  • 「分支太多,管理混乱」:我曾经见过一个团队,GitFlow用了半年,分支列表里躺着30多个没人合并的feature分支。我的建议是,定期清理。每周五下午,花半小时把已经合并的分支删掉。别心疼,Git历史里还能找到。
  • 「合并冲突解决到崩溃」:嵌入式项目里,头文件、配置文件、链接脚本这些文件特别容易冲突。我的做法是,把这些文件单独放在一个「公共模块」里,谁要改,先通知大家。说白了,就是加一层人工协调。
  • 「CI跑太久,等得心焦」:Trunk-Based Development要求每次提交都跑CI,但嵌入式项目编译一次可能半小时。怎么办?我的方案是,分两步走:先跑一个「快速检查」(语法检查、单元测试),几分钟搞定;再跑一个「完整编译」,放到后台慢慢跑。这样开发者不用干等着。

我曾经... 有一次,团队里有人把编译脚本改坏了,结果CI跑了40分钟才发现。从那以后,我就在CI里加了一个「预检查」步骤:先检查编译脚本的语法,再检查依赖关系。这样,大部分低级错误在30秒内就能被发现。

3.5 我的最终建议

其实,没有完美的Git工作流。GitFlow和Trunk-Based Development,说白了就是两种不同的「平衡」——GitFlow平衡了稳定性和灵活性,Trunk-Based Development平衡了速度和协作。

我的建议是:

  • 先从小团队开始,用Trunk-Based Development跑起来。等团队大了、产品线多了,再慢慢引入GitFlow的分支策略。
  • 别把流程定得太死。我见过一些团队,GitFlow的规则写了20页,结果没人看。流程是为人服务的,不是反过来。
  • 定期回顾。每两个月,花半天时间,看看当前的工作流有没有问题。该调整就调整,别怕改。

嗯,Git工作流这块,今天就聊到这儿。下一章,我会讲讲CI/CD流水线的搭建,到时候会用到今天讲的分支策略。咱们到时候见。