上篇聊了代码审查,PR机制是建立在Git之上的。版本管理是团队协作的基础设施,不会版本管理的工程师就像不会存钱的会计——基本功能都缺失。Git是每个机器人工程师必须熟练掌握的工具。

机器人项目的版本管理比普通软件项目复杂一些。原因有几个:代码仓库多(感知、控制、导航各自独立)、有大文件(URDF模型、点云地图、训练好的模型文件)、需要和硬件版本对应(固件版本、驱动版本)。面试时如果你能聊清楚Git在机器人项目中的特殊用法,会加分不少——这说明你有实际工程经验。

分支策略

机器人项目常用的分支策略有两种:

Git Flow:main分支始终保持可发布状态,develop分支做日常开发,feature分支从develop拉出来开发新功能,完成后合回develop。发布时从develop切release分支,修完bug打上tag合回main。适合有固定发布周期的项目。

Trunk Based Development:所有人直接在main分支上开发,用feature flag控制新功能的开关。适合持续部署的团队,要求代码审查和自动化测试非常成熟。

大多数机器人团队用Git Flow或者它的变体。因为机器人发布往往和硬件版本绑定,需要有明确的发布节点。你不太可能给已经出厂的机器人推送一个"持续部署"的更新。而且硬件迭代周期长,软件需要同时维护多个版本——新机器用最新代码,老机器用稳定分支打补丁。

大文件管理

机器人项目有个头疼的问题:大文件。点云地图动辄几百MB,深度学习模型文件几十到几百MB,Gazebo世界文件里的网格模型也不小。这些文件直接放Git仓库里,仓库体积会迅速膨胀,clone速度越来越慢。

解决方案有几种:

Git LFS(Large File Storage):最主流的方案。大文件不直接存在Git仓库里,而是存在LFS服务器上,Git仓库里只保存一个指针。clone时默认不下载LFS文件,需要时再拉取。缺点是LFS服务器需要额外维护,而且有存储空间限制。

Git Annex:类似LFS但更灵活,支持多种存储后端(S3、NAS、USB硬盘都行)。适合不想依赖第三方服务的团队。

外部存储+引用:最简单的方案。大文件放在NAS或者云存储上,Git仓库里只保存一个下载链接或者路径引用。缺点是版本对应关系需要手动管理。

# Git LFS基本用法
git lfs install
git lfs track "*.pcd"
git lfs track "*.onnx"
git add .gitattributes
git add maps/ models/
git commit -m "Add map and model files via LFS"

多仓库协调

机器人项目通常有多个代码仓库:感知模块一个仓库、导航模块一个仓库、控制模块一个仓库、机器人描述(URDF/Mesh)一个仓库。这些仓库之间有版本依赖关系——导航v2.3必须配合感知v1.5才能正常工作。

怎么管理这种跨仓库的版本依赖?

Git Submodule:在主仓库里引用子仓库的特定commit。优点是版本锁定精确,缺点是操作复杂,很多工程师搞不清楚submodule的更新流程。

vcstool:ROS社区常用的工具。用一个yaml文件描述所有仓库的地址和版本,一条命令checkout所有仓库到正确版本。比submodule简单很多。ros2的源码管理就是用vcstool,你可以看看它的repositories.yaml文件作为参考。

还有一种思路是monorepo——所有代码放在一个仓库里。Google就是典型的monorepo。优点是版本一致性天然保证,不需要跨仓库同步。缺点是仓库太大,Git操作变慢。机器人项目如果团队不大(10人以内),monorepo其实是个不错的选择,省去了多仓库协调的麻烦。

# repositories.yaml
repositories:
  perception:
    type: git
    url: https://github.com/myorg/perception.git
    version: v1.5.0
  navigation:
    type: git
    url: https://github.com/myorg/navigation.git
    version: v2.3.0
  robot_description:
    type: git
    url: https://github.com/myorg/robot_description.git
    version: main
vcs import < repositories.yaml

Tag和发布管理

机器人项目的发布(release)需要记录的信息比普通软件多。一个完整的发布tag应该包含:

  • 软件版本号(遵循语义化版本:major.minor.patch)
  • 对应的固件版本
  • 对应的硬件版本(PCB版本号)
  • 标定参数版本
  • 已知问题和限制

这些信息通常写在一个CHANGELOG.md或者release notes里,和tag关联。出了问题需要回溯的时候,能精确知道当时用的是哪个版本的代码、跑在哪块硬件上、用的什么标定参数。

Commit规范

版本管理的质量很大程度上取决于commit message的质量。好的commit历史就像一本项目日记,能帮你快速定位"这个bug是什么时候引入的"。

我们团队遵循Conventional Commits规范:

feat(navigation): 添加动态障碍物预测功能
fix(control): 修复PID积分饱和导致的超调问题
perf(perception): 优化点云降采样速度提升40%
docs(readme): 更新安装说明和依赖版本要求

每条commit message包含三部分:类型(feat/fix/perf/docs等)、作用域(哪个模块)、简短描述。复杂的改动在正文里补充详细说明,解释"为什么"而不是"做了什么"。

有个纪律很重要:一个commit只做一件事。不要在一个commit里既改算法又改UI还修了一个typo。这样出问题需要回滚的时候,你不需要把不相关的改动一起回滚。用git add -p可以按代码块分阶段暂存,不需要把所有改动一次性提交。

面试追问

"你们怎么处理紧急bug修复?"从main分支切一个hotfix分支,修复后同时合回main和develop。hotfix分支要走完整的代码审查和测试流程,不能因为紧急就跳过。如果bug影响已经部署的机器人,还需要评估是否需要OTA更新。

"Git rebase和merge有什么区别?你们用哪个?"rebase把提交历史变干净,merge保留完整的分支历史。我们团队的规范是:feature分支用rebase保持和develop同步,合入develop时用merge。main分支上的历史永远是线性的,方便追溯。

"仓库被误推了大文件怎么办?"用git filter-repo或者BFG Repo-Cleaner清理。清理后所有人需要重新clone仓库。这是为什么我们要在CI里加大文件检测——PR里包含超过10MB的文件就自动拒绝。


版本管理是团队协作的地基。地基打不好,上面的代码审查、CI/CD、发布管理全都受影响。机器人项目的版本管理比纯软件项目多了一些维度——硬件版本、固件版本、标定参数——这些都要纳入版本管理的范畴。

我见过一个团队因为没有做好版本管理,花了整整一周时间排查一个问题。最后发现是有人改了URDF模型里的关节限位参数,但没有更新版本号,导致测试用的模型和实际部署的模型不一致。如果版本管理做好了,这种问题根本不会发生。

下一篇聊技术文档写作。代码写得好不够,还得把设计思路、接口规范、使用手册写清楚。文档能力是工程师的隐形竞争力——会写文档的人,在团队里的影响力远大于他的代码产出。


如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。

「机器人软件开发面试·从入门到精通」连载系列 

上一篇:第331篇 代码审查——怎么review别人的代码

下一篇预告:第333篇 技术文档写作——工程师的隐形竞争力

有任何问题欢迎评论区留言,我会尽量回复。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐