1. 项目概述
作为一名在嵌入式Linux领域摸爬滚打多年的开发者,我深知版本控制在嵌入式项目中的重要性。不同于常规软件开发,嵌入式项目往往涉及交叉编译环境、设备树配置、内核定制等复杂操作,一个可靠的Git工作流能让我们避免很多"昨晚还能编译,今早就报错"的噩梦。
今天要分享的这套工作流,是我在多个量产级嵌入式项目中验证过的实战方案。从最基础的SSH认证配置,到Gerrit代码审核的完整推送流程,我会把每个环节的"为什么这么做"和"怎么避免踩坑"都讲清楚。特别适合正在从单片机开发转向Linux嵌入式系统的工程师,或者需要规范团队协作流程的技术负责人。
2. 开发环境准备
2.1 基础工具链配置
嵌入式Linux开发首先需要搭建交叉编译环境。以常见的ARM架构为例:
bash复制sudo apt-get install gcc-arm-linux-gnueabihf \
build-essential \
git-core \
gitk \
git-gui
这里有几个关键点需要注意:
- 编译器版本必须与目标板内核版本匹配
- 建议使用
git-core而非默认git包,包含更多开发者工具 - 安装gitk/git-gui方便可视化操作
提示:嵌入式开发强烈建议使用相同版本的Docker容器作为编译环境,避免"在我机器上能编译"的问题。
2.2 SSH认证配置
Gerrit强制使用SSH协议,我们先配置免密登录:
bash复制ssh-keygen -t ed25519 -C "your_email@example.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
将公钥添加到Gerrit服务器的"Settings -> SSH Keys"页面。测试连接:
bash复制ssh -p 29418 username@gerrit.example.com
常见问题排查:
- 端口29418是Gerrit默认SSH端口
- 如果提示"Permission denied",检查~/.ssh/config是否配置正确
- 使用
ssh -Tv参数查看详细连接过程
3. Git基础工作流定制
3.1 仓库初始化规范
嵌入式项目建议采用以下目录结构:
code复制project-root/
├── buildroot/ # Buildroot配置
├── linux/ # 定制内核
├── bootloader/ # U-Boot相关
└── app/ # 应用层代码
初始化命令示例:
bash复制git init
git checkout -b develop
touch README.md
git add . && git commit -m "Initial commit"
3.2 分支策略设计
推荐采用改进版Git Flow:
code复制main - 仅发布稳定版本
release/* - 版本预发布分支
develop - 主要开发分支
feature/* - 功能开发分支
hotfix/* - 紧急修复分支
创建功能分支:
bash复制git checkout develop
git pull origin develop
git checkout -b feature/add-spi-driver
4. Gerrit集成实战
4.1 提交规范配置
安装commit-msg钩子(Gerrit强制要求Change-Id):
bash复制scp -p -P 29418 username@gerrit.example.com:hooks/commit-msg .git/hooks/
提交示例:
bash复制git commit -m "drivers: add SPI flash support
Add support for MX25L1606E SPI flash chip.
Signed-off-by: Your Name <your.email@example.com>
Change-Id: Ixxxxxx"
4.2 代码推送流程
- 本地开发完成后:
bash复制git push origin HEAD:refs/for/develop
- 在Gerrit页面进行Code Review
- 审核通过后点击"Submit"按钮合并
重要:Gerrit的refs/for/分支是特殊引用,不能直接git pull获取
4.3 冲突解决方案
当出现冲突时:
bash复制git fetch origin
git rebase -i origin/develop
# 解决冲突后
git add .
git rebase --continue
git push origin HEAD:refs/for/develop
5. 嵌入式开发特殊处理
5.1 大文件存储方案
嵌入式项目常遇到内核镜像等二进制文件,建议:
bash复制git lfs install
git lfs track "*.dtb"
git lfs track "*.bin"
5.2 子模块管理技巧
对于U-Boot等子模块:
bash复制git submodule add https://github.com/u-boot/u-boot.git bootloader
git submodule update --init --recursive
更新子模块:
bash复制git submodule foreach git pull origin master
6. 自动化集成方案
6.1 CI/CD管道配置
在.gitlab-ci.yml或Jenkinsfile中添加:
yaml复制build:
stage: build
script:
- make defconfig
- make all
artifacts:
paths:
- output/images/
6.2 静态检查集成
使用pre-commit钩子:
yaml复制repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: check-merge-conflict
7. 常见问题排坑指南
7.1 认证失败问题
现象:git push时提示"Permission denied"
解决方案:
- 检查~/.ssh/config配置:
code复制Host gerrit Hostname gerrit.example.com Port 29418 User your_username - 测试SSH连接:
ssh gerrit - 确认公钥已添加到Gerrit账户
7.2 Change-Id丢失问题
现象:提交时提示"missing Change-Id"
解决方案:
- 确认.git/hooks/commit-msg存在且可执行
- 尝试手动添加:
bash复制
在消息底部添加空行和Change-Idgit commit --amend
7.3 子模块更新问题
现象:git submodule update失败
解决方案:
- 清除缓存:
bash复制
git submodule deinit -f . git submodule update --init --recursive - 检查.gitmodules文件配置
8. 高级技巧分享
8.1 交互式rebase优化历史
合并多个提交:
bash复制git rebase -i HEAD~5
# 将pick改为squash
8.2 二分法定位问题
当出现回归问题时:
bash复制git bisect start
git bisect bad
git bisect good v1.0
# 测试当前版本
git bisect good/bad
8.3 多仓库协同开发
使用repo工具管理:
bash复制repo init -u https://gerrit.example.com/manifest
repo sync
repo start feature/new-driver --all
9. 性能优化实践
9.1 浅克隆加速
对于大型仓库:
bash复制git clone --depth=1 https://gerrit.example.com/linux
9.2 稀疏检出节省空间
只检出需要的目录:
bash复制git config core.sparseCheckout true
echo "drivers/usb/" >> .git/info/sparse-checkout
git checkout develop
10. 团队协作规范建议
-
提交消息规范:
- 首行不超过50字符
- 正文每行不超过72字符
- 空行分隔标题和正文
- 包含Signed-off-by
-
Code Review原则:
- 每个变更不超过300行
- 重点审查硬件相关代码
- 必须通过实际设备测试
-
分支命名约定:
- feature/: 新功能开发
- bugfix/: 问题修复
- refactor/: 重构代码
- 禁止直接push到main分支