版本控制策略:Git Flow vs Trunk-Based Development
版本控制这事儿,说起来简单,做起来全是坑。我在嵌入式团队里见过太多因为分支策略没选好,导致发布延期、合并冲突炸裂的惨案。今天咱们就聊聊两种主流策略——Git Flow 和 Trunk-Based Development,以及它们在嵌入式场景下该怎么选。
Git Flow:经典但有点重
Git Flow 大家应该都听过。它有 master、develop、feature、release、hotfix 五类分支。听起来很完整对吧?但说实话,我在嵌入式项目里用 Git Flow 时,经常觉得它太「重」了。
举个例子。你想想看,嵌入式开发往往涉及硬件依赖,一个 feature 分支可能开发了两周,等合并回 develop 时,发现底层驱动接口已经变了。合并冲突能让你改到怀疑人生。我个人习惯是,如果团队超过 10 人,且产品有多个并行版本(比如 v1.0 维护、v2.0 开发),Git Flow 确实能帮你理清脉络。但如果是小团队、单产品线,它反而成了负担。
Trunk-Based Development:轻量但要求高
Trunk-Based Development(主干开发)就简单多了。所有开发者都往 main 或 trunk 上提交,分支存活时间不超过一天。说白了,就是「频繁集成、小步快跑」。
我记得有一次在 IoT 项目里,我们强制要求每天至少合并一次代码到主干。刚开始大家都很抗拒,觉得「我功能还没写完呢」。但坚持了两周后,效果出来了——合并冲突几乎消失了,因为每次改动都很小。而且,一旦发现编译错误,几分钟内就能定位到是谁提交的。
嵌入式场景下的分支策略选择
嵌入式开发有个特点:硬件版本多、编译链复杂、烧录验证慢。所以分支策略不能照搬互联网公司的做法。我总结了几条经验:
- 硬件依赖重时,用 Git Flow 的变体:比如只保留
master和feature分支,去掉develop和release。因为硬件驱动经常需要单独维护,feature 分支可以按硬件模块来命名,比如feature/stm32-i2c-driver。 - 固件迭代快时,用 Trunk-Based:比如消费类 IoT 产品,每周都要发版。这时候主干开发配合 feature toggle(特性开关)是最佳选择。我曾经在智能家居项目里用过,效果不错。
- 混合策略:有些团队会采用「主干开发 + 发布分支」的模式。日常开发都在主干上,到了发布节点,从主干拉一个
release/v1.x分支,只做 bug 修复。这样既保证了集成频率,又保留了发布稳定性。
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 多硬件平台并行 | Git Flow 变体 | 每个硬件版本可独立维护分支 |
| 单产品快速迭代 | Trunk-Based | 减少合并成本,快速反馈 |
| 固件+App 混合开发 | 混合策略 | 固件用 Git Flow,App 用 Trunk-Based |
代码评审流程
代码评审这事儿,很多嵌入式团队做得不好。要么流于形式,要么干脆不做。我见过最夸张的情况——评审人只看文件名,连代码都没打开就点了「Approve」。嗯,这比不评审还糟糕。
我个人习惯的评审流程是这样的:
- 提交前自检:开发者自己跑一遍静态检查(比如 PC-Lint、Cppcheck)和单元测试。确保没有低级错误。
- 创建 Pull Request:PR 描述要写清楚「改了啥、为什么改、怎么验证的」。我曾经要求团队必须附上编译通过截图和烧录验证结果,否则不审。
- 指定评审人:至少 2 人。一个熟悉业务逻辑,一个熟悉底层硬件。避免「一个人说了算」的情况。
- 评审要点:重点关注内存泄漏、指针越界、中断安全、可移植性。嵌入式代码里,这些是致命问题。
- 合并策略:建议用 Squash Merge 或 Rebase Merge,保持主干历史干净。我比较喜欢 Squash,因为每次 PR 只产生一个提交,回溯时特别清晰。
最后说一句,版本控制和代码评审不是银弹。工具再好,人也得跟上。我见过用 Git Flow 但依然一团糟的团队,也见过用 Trunk-Based 但效率极高的团队。关键还是看执行力和文化。你想想看,如果每个人提交前都自觉跑一遍测试,评审时认真看每一行代码,用什么策略其实差别不大。
好了,这一章就聊到这儿。下一章咱们讲讲持续集成在嵌入式环境下的落地——那才是真正的硬骨头。