【保姆级】Git第四课:远程协作与GitLab工作流——从“单兵作战“到“团队协同“的嵌入式开发管理
【摘要/导读】
本文专为从个人开发转向团队协作的嵌入式工程师设计,系统讲解远程仓库管理、GitLab协作流程与嵌入式资源管控。针对"公共驱动库版本不统一导致编译失败"、“固件bin文件撑爆仓库”、"代码审查流于形式"三大团队协作痛点,提供可落地的远程工作流方案。
核心内容包括:
- 远程仓库架构:
origin与upstream多远程管理、裸仓库(bare repo)作为中央备份、多远程推送策略(GitLab主仓+Gitee镜像+本地NAS) - GitLab协作流:Fork模式 vs 共享仓库分支模式、Merge Request(MR)嵌入式代码审查清单(MISRA规范检查、寄存器修改审查、版本号更新校验)、CI/CD流水线自动编译生成HEX文件
- 子模块管理:
git submodule管理CMSIS-Pack/HAL库/BSP公共驱动,版本锁定策略防止"更新HAL导致整组代码编译失败",以及subtree替代方案对比 - 大文件管控:Git LFS管理硬件手册PDF、固件bin、Altium原理图/PCB文件,避免源码仓体积指数膨胀,配合
.gitattributes自动拦截大文件
适合已掌握分支管理的开发者建立团队级协作规范,掌握"多远程备份"、“子模块版本冻结”、“MR审查清单"等进阶技能,避开"直接push到main”、“子模块游离HEAD”、"用源码仓传HEX文件"等团队协作灾难性错误。
关键词:Git远程协作;GitLab工作流;Merge Request;git submodule;Git LFS;嵌入式团队管理;CI/CD自动编译;CMSIS-Pack版本锁定;裸仓库备份
📑 文章目录
- 回顾:从本地到远程的思维跃迁
- 一、远程仓库架构设计
- 二、GitLab协作工作流
- 三、CI/CD集成:自动编译与HEX生成
- 四、子模块管理:公共驱动库的版本锁定
- 五、Git LFS:大文件与二进制资源管理
- 六、阶段实战:完整的多人协作流程
- 七、团队协作安全守则与灾难恢复
- 总结与下篇预告
回顾:从本地到远程的思维跃迁
在前三阶段,我们掌握了本地仓库的管理。但嵌入式开发极少"单兵作战"——你需要:
- 与硬件工程师协作:他更新了Altium原理图(v2.0增加了一个传感器),你需要同步修改固件驱动
- 与测试团队协作:他们基于
v1.0.3固件发现了Bug,你需要精确定位该版本代码并修复 - 与供应链协作:BMI323芯片停产,替换为BMI270,HAL库和驱动代码需要统一变更
本地Git的局限:
- 笔记本硬盘损坏 = 代码丢失(即使本地有仓库)
- 同事无法获取你的
feature/can-fd分支进行联调 - 无法追溯"谁、在什么时候、修改了哪个寄存器"(本地提交不关联代码审查记录)
远程协作的核心价值:
- 集中备份:GitLab服务器作为"权威副本",本地只是"工作副本"
- 流程管控:通过MR(Merge Request)强制代码审查,防止未经审核的寄存器配置进入量产分支
- 自动化:提交代码后自动编译生成HEX,测试团队直接下载烧录,无需打扰固件工程师
一、远程仓库架构设计
1.1 远程引用与追踪分支
当你执行git clone后,Git自动建立了以下映射:
# 查看远程引用
git branch -r
# origin/HEAD -> origin/main
# origin/main
# origin/develop
# origin/feature/can-fd
# 查看追踪关系(upstream)
git branch -vv
# * main 2a3b4c5 [origin/main] feat: add CAN FD
# develop 3c4d5e6 [origin/develop: ahead 2] fix: IMU drift
关键概念:
- 远程引用(Remote Refs):
origin/main是远程仓库main分支的本地镜像,只读(除非你push) - 追踪分支(Tracking Branch):本地
main追踪origin/main,执行git pull时Git知道从哪拉取 - 上游(Upstream):本地分支对应的远程分支,通过
git push -u origin feature/xxx建立
实操检查:
# 查看当前分支的上游
git rev-parse --abbrev-ref --symbolic-full-name @{u}
# 输出:origin/main
# 如果提示"no upstream configured",需要先建立追踪
git branch --set-upstream-to=origin/main main
1.2 多远程管理:origin、upstream与镜像
场景:公司主仓在GitLab,但你希望同时推送到Gitee(国内访问快)和本地NAS(离线备份)。
# 查看当前远程
git remote -v
# origin git@gitlab.company.com:firmware/imu.git (fetch)
# origin git@gitlab.company.com:firmware/imu.git (push)
# 添加Gitee镜像(命名为gitee)
git remote add gitee https://gitee.com/company/imu.git
# 添加本地NAS裸仓库(命名为backup)
git remote add backup ssh://nas.local/volume1/git/imu.git
# 查看所有远程
git remote -v
# origin git@gitlab.company.com:firmware/imu.git (fetch)
# origin git@gitlab.company.com:firmware/imu.git (push)
# gitee https://gitee.com/company/imu.git (fetch)
# gitee https://gitee.com/company/imu.git (push)
# backup ssh://nas.local/volume1/git/imu.git (fetch)
# backup ssh://nas.local/volume1/git/imu.git (push)
多远程推送:
# 推送到所有远程(手动)
git push origin main
git push gitee main
git push backup main
# 或者配置一次性推送多个(修改.git/config)
git config remote.all.url git@gitlab.company.com:firmware/imu.git
git config remote.all.url git@gitee.com:company/imu.git
# 然后:git push all main
Fork模式下的upstream:
如果你Fork了公司主仓到自己的GitLab账号:
# clone自己的Fork
git clone git@gitlab.com:yourname/imu-fork.git
cd imu-fork
# 添加原仓库为upstream(用于同步主仓最新代码)
git remote add upstream git@gitlab.company.com:firmware/imu.git
# 日常同步流程
git fetch upstream
git checkout main
git merge upstream/main # 或 rebase
git push origin main # 推送到自己的Fork
1.3 裸仓库(Bare Repo):团队的中央备份
裸仓库是没有工作区的仓库(只有.git目录的内容),适合作为中央服务器。
在公司NAS上创建裸仓库(用于内网备份):
# 在NAS服务器上(Linux)
mkdir -p /volume1/git/imu.git
cd /volume1/git/imu.git
git init --bare
# 本地开发者添加远程并推送
git remote add nas ssh://nas.local/volume1/git/imu.git
git push -u nas main
裸仓库 vs 普通仓库:
| 特性 | 裸仓库(–bare) | 普通仓库 |
|---|---|---|
| 工作区 | 无 | 有 |
| 能否直接编辑文件 | 不能 | 能 |
| 能否push | 能(作为中央仓) | 能,但可能冲突 |
| 适用场景 | GitLab服务器、NAS备份 | 开发者本地 |
嵌入式团队建议:在工厂内网部署一台GitLab或Gitea服务器(裸仓库管理),外网再同步到GitHub/GitHub,实现"内网开发+外网备份"的双保险。
二、GitLab协作工作流
2.1 Fork模式 vs 共享仓库分支模式
模式A:共享仓库分支模式(推荐10人以下嵌入式小团队)
所有人直接在公司主仓创建分支:
# 小张
git checkout -b feature/can-filter-zhang
git push -u origin feature/can-filter-zhang
# 小李
git checkout -b feature/imu-calibration-li
git push -u origin feature/imu-calibration-li
优点:操作简单,权限管理直接
缺点:需要严格控制push权限(防止直接push到main)
模式B:Fork模式(推荐开源项目或大型团队)
每个人Fork主仓到自己的账号,开发完成后通过MR贡献代码:
# 小张Fork主仓到 gitlab.com/zhangsan/imu
git clone git@gitlab.com:zhangsan/imu.git
git remote add upstream git@gitlab.company.com:firmware/imu.git
# 开发特性
git checkout -b feature/can-filter
git push origin feature/can-filter
# 在GitLab网页发起Merge Request到 upstream/main
优点:完全隔离,不会污染主仓;适合外部协作者
缺点:操作复杂,需要频繁同步upstream
嵌入式团队选择建议:
- 公司内部固件团队(<15人):共享仓库+保护分支,效率最高
- 外包/高校合作/开源社区:Fork模式,安全可控
2.2 Merge Request:嵌入式代码审查清单
MR(Merge Request)是代码进入主仓前的质量关卡。对于嵌入式固件,审查不能只看"代码风格",必须检查硬件安全性。
创建MR时的规范模板(在项目根目录创建.gitlab/merge_request_templates/default.md):
## 变更概述
- [ ] 修复Bug / 新功能 / 文档更新 / 重构
- [ ] 关联Issue:#xxx
## 硬件影响评估(嵌入式必填)
- [ ] 是否修改寄存器配置?如是,列出所有修改的寄存器及地址:
- [ ] 是否影响已量产硬件(v1.0/v1.1)的兼容性?
- [ ] 是否更新硬件版本标记(config.h中的HW_VERSION)?
- [ ] 是否在目标硬件上实测通过?(提供测试环境:温度/电压/负载)
## 代码审查Checklist
- [ ] 编译零警告(Keil/VS Code+GCC)
- [ ] 新增函数已添加Doxygen注释
- [ ] 未提交编译产物(.hex/.bin/.map)
- [ ] 敏感信息(WiFi密码/API Key)已移除
- [ ] 原子提交(每个commit只做一件事)
## 测试证据
- [ ] 单元测试通过截图
- [ ] 硬件在环测试日志(如CAN分析仪数据)
- [ ] 功耗测试数据(如适用)
审查者重点关注:
- 寄存器修改:
FDCAN1->NBTP从0x06000F01改为0x02000F01,是否影响旧硬件? - 时序变更:延时函数
HAL_Delay(10)改为HAL_Delay(5),是否满足传感器上电时序? - 资源占用:新增DMA通道是否与现有外设冲突?
- 版本号:
main分支的VERSION_STRING是否已更新?
2.3 保护分支与权限矩阵
GitLab保护分支设置(Settings → Repository → Protected Branches):
| 分支 | 允许Push | 允许Merge | 适用角色 | 说明 |
|---|---|---|---|---|
main |
❌ No one | ✅ Maintainers | 技术主管/项目经理 | 仅通过MR合并,且需2人审查 |
develop |
❌ No one | ✅ Developers | 资深工程师 | 通过MR合并,需1人审查 |
release/* |
❌ No one | ✅ Maintainers | 技术主管 | 版本发布分支 |
feature/* |
✅ Developers | ❌ N/A | 所有开发者 | 自由push,但合并需MR |
权限矩阵示例(5人团队):
| 成员 | main | develop | feature/* | hotfix/* | 说明 |
|---|---|---|---|---|---|
| 技术主管 | Merge only | Merge only | Push | Merge | 负责最终发布审核 |
| 固件组长 | ❌ | Merge | Push | Push | 负责develop集成 |
| 工程师A | ❌ | ❌ | Push | ❌ | 日常开发 |
| 工程师B | ❌ | ❌ | Push | ❌ | 日常开发 |
| 测试工程师 | ❌ | ❌ | Push | ❌ | 提交测试脚本和用例 |
三、CI/CD集成:自动编译与HEX生成
3.1 GitLab Runner与嵌入式编译环境
GitLab CI/CD通过.gitlab-ci.yml定义流水线,在代码提交后自动执行编译、测试、生成产物。
嵌入式编译环境选择:
- Keil MDK:Windows Runner + Keil命令行(
UV4.exe -b project.uvprojx),需授权 - VS Code + ARM GCC:Linux Runner +
arm-none-eabi-gcc,免费且适合CI - STM32CubeIDE:Headless模式编译,较复杂
推荐方案:项目同时支持Keil(日常开发)和GCC(CI编译),通过Makefile或CMake统一管理。
3.2 .gitlab-ci.yml实战:Keil/VS Code+GCC
示例配置(GCC + Makefile):
# .gitlab-ci.yml
stages:
- build
- test
- release
variables:
GIT_SUBMODULE_STRATEGY: recursive # 自动拉取子模块
# 编译阶段
build_firmware:
stage: build
image: gcc-arm-none-eabi:latest # Docker镜像
script:
- make clean
- make all
- ls build/IMU_*.hex
- ls build/IMU_*.bin
artifacts:
name: "IMU_Firmware_$CI_COMMIT_TAG"
paths:
- build/*.hex
- build/*.bin
- build/*.map
expire_in: 1 month # 产物保留1个月
only:
- main
- develop
- merge_requests
# 静态检查(MISRA-C规则)
static_analysis:
stage: test
image: cppcheck:latest
script:
- cppcheck --enable=all --std=c99 --suppress=missingIncludeSystem Core/Src/
allow_failure: true # 暂时允许失败,不阻塞流水线
# 发布阶段(仅打标签时执行)
release_firmware:
stage: release
image: alpine:latest
script:
- echo "Release $CI_COMMIT_TAG"
- |
echo "Firmware Info:" > RELEASE_NOTES.txt
echo "Version: $CI_COMMIT_TAG" >> RELEASE_NOTES.txt
echo "Commit: $CI_COMMIT_SHA" >> RELEASE_NOTES.txt
echo "Date: $CI_COMMIT_TIMESTAMP" >> RELEASE_NOTES.txt
artifacts:
name: "Release_$CI_COMMIT_TAG"
paths:
- build/*.hex
- build/*.bin
- RELEASE_NOTES.txt
only:
- tags # 仅在打标签时触发
Keil命令行编译(Windows Runner):
build_keil:
stage: build
tags:
- windows
- keil
script:
- C:\Keil_v5\UV4\UV4.exe -b Project\IMU.uvprojx -o build_log.txt
- type build_log.txt
artifacts:
paths:
- Project\Objects\*.hex
3.3 产物管理与版本追溯
**产物(Artifacts)**是CI生成的文件,GitLab会自动存储,团队可直接下载:
GitLab Project → CI/CD → Pipelines → 某次Pipeline → Artifacts
版本追溯策略:
- 每次
main分支的提交都会生成HEX,但不长期保存(expire_in: 1 week) - 每次标签(Tag)提交生成的HEX永久保存,并关联Release页面
- 测试团队烧录固件时,必须记录Git Commit Hash(从
RELEASE_NOTES.txt获取),确保问题可复现
固件版本号自动生成:
# Makefile
VERSION := $(shell git describe --tags --always --dirty)
# 输出示例:v1.0.0-5-g2a3b4c5(距离v1.0.0有5个提交,当前commit为2a3b4c5)
# 或 v1.0.0-dirty(有未提交修改,禁止发布)
CFLAGS += -DVERSION_STRING=\"$(VERSION)\"
// main.c
const char* firmware_version = VERSION_STRING;
// 启动时通过UART打印版本号,测试团队记录
printf("FW Version: %s\r\n", firmware_version);
四、子模块管理:公共驱动库的版本锁定
4.1 何时使用子模块
嵌入式团队的典型需求:
- CMSIS-Pack(ARM官方库):所有项目共用,但版本需统一(如v5.9.0)
- 公司公共HAL封装:如
company_can_stack,多个产品(IMU、GPS、飞控)共用 - 第三方开源库:如FatFs、FreeRTOS、MAVLink
不使用子模块的后果:
- 工程师A拷贝了CMSIS v5.8.0,工程师B拷贝了v5.9.0,合并时产生大量无意义冲突
- 公共库更新后,所有项目需要手动复制粘贴,容易遗漏
4.2 submodule实战:CMSIS-Pack与HAL库
添加子模块:
# 在项目根目录
git submodule add https://github.com/ARM-software/CMSIS_5.git Drivers/CMSIS
# 默认克隆到 Drivers/CMSIS 目录
# 查看子模块状态
git submodule status
# 4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3 Drivers/CMSIS (v5.9.0)
# 提交子模块配置(.gitmodules文件和子模块commit指针)
git add .gitmodules Drivers/CMSIS
git commit -m "chore(deps): add CMSIS v5.9.0 as submodule
- Used for core_cm4.h and DSP library
- Locked to tag v5.9.0 (commit 4a5b6c7)"
.gitmodules文件内容:
[submodule "Drivers/CMSIS"]
path = Drivers/CMSIS
url = https://github.com/ARM-software/CMSIS_5.git
branch = main # 可选,追踪分支
克隆包含子模块的项目:
# 方法1:递归克隆(推荐)
git clone --recursive git@gitlab.company.com:firmware/imu.git
# 方法2:普通克隆后初始化子模块
git clone git@gitlab.company.com:firmware/imu.git
cd imu
git submodule update --init --recursive
4.3 子模块更新与版本冻结
查看子模块是否有更新:
cd Drivers/CMSIS
git fetch origin
git log HEAD..origin/main --oneline # 查看上游新提交
cd ../..
更新子模块版本(谨慎操作,需团队通知):
cd Drivers/CMSIS
git checkout v5.9.1 # 切换到新版本标签
cd ../..
git add Drivers/CMSIS # 更新主仓记录的子模块commit指针
git commit -m "chore(deps): upgrade CMSIS from v5.9.0 to v5.9.1
- Fixes Cortex-M4 FPU context save bug
- Verified with IMU sensor fusion test"
关键原则:子模块的commit指针是精确锁定的。即使上游仓库更新了100个提交,你的项目仍然使用上次记录的那个commit,确保可复现编译。
批量更新所有子模块:
git submodule update --remote # 拉取所有子模块的最新commit(危险!)
git submodule update --remote Drivers/CMSIS # 仅更新指定子模块
4.4 subtree替代方案
git subtree是子模块的替代方案,将外部库代码直接合并到主仓历史中。
对比:
| 特性 | submodule | subtree |
|---|---|---|
| 代码位置 | 外部仓库,主仓只存指针 | 直接存在于主仓目录中 |
| 克隆 | 需--recursive或后续初始化 |
普通clone即可,无依赖 |
| 版本控制 | 精确锁定commit | 通过merge commit管理 |
| 修改子模块代码 | 需进入子模块目录单独commit | 直接修改,像普通文件一样提交 |
| 适用场景 | 第三方库(不常修改) | 公司内部公共库(需要频繁修改) |
subtree添加:
git subtree add --prefix=Drivers/CMSIS https://github.com/ARM-software/CMSIS_5.git v5.9.0 --squash
# --squash 压缩历史,避免主仓历史被外部库提交淹没
嵌入式团队建议:
- 第三方库(CMSIS、FreeRTOS、FatFs):用
submodule,不修改其代码 - 公司内部公共库(公司CAN协议栈、传感器抽象层):用
subtree,方便修改且同事无需学习子模块命令
五、Git LFS:大文件与二进制资源管理
5.1 为什么源码仓不能存HEX/PDF
Git基于差异存储,对文本文件高效,但对二进制文件是灾难:
| 文件类型 | 大小 | 每次修改的存储成本 | 10次提交后仓库增量 |
|---|---|---|---|
main.c |
5KB | 仅存储差异(~200B) | ~2KB |
IMU_v1.0.hex |
128KB | 存储完整文件(128KB) | ~1.28MB |
Datasheet.pdf |
3MB | 存储完整文件(3MB) | ~30MB |
PCB.PcbDoc |
15MB | 存储完整文件(15MB) | ~150MB |
后果:3个月后,源码仓从10MB膨胀到500MB,新同事git clone需要半小时,且历史无法精简(因为旧版本的.hex仍存在于objects中)。
5.2 LFS安装与配置
Git LFS(Large File Storage)将大文件内容存储在独立服务器,Git仓库只存指针文件(文本,约130字节)。
安装:
# Windows(Git for Windows已内置)
git lfs install
# Linux
sudo apt-get install git-lfs
git lfs install
追踪大文件:
# 追踪所有PDF手册
git lfs track "*.pdf"
# 追踪所有Altium文件
git lfs track "*.PcbDoc"
git lfs track "*.SchDoc"
git lfs track "*.PrjPcb"
# 追踪固件产物(如果确实需要存储在仓库中)
git lfs track "Release/*.hex"
git lfs track "Release/*.bin"
# 查看已追踪规则
git lfs track
提交配置:
# .gitattributes文件已自动生成/修改
git add .gitattributes
git add Datasheets/BMI323.pdf
git commit -m "docs: add BMI323 datasheet via LFS"
git push origin main
验证:
# 查看哪些文件被LFS管理
git lfs ls-files
# 6a7b8c9d * Datasheets/BMI323.pdf (3.2 MB)
# 1b2c3d4e * Release/IMU_v1.0.0.hex (128 KB)
5.3 .gitattributes自动拦截策略
在项目根目录创建.gitattributes,与.gitignore配合实现自动拦截:
# 强制LFS管理(即使忘记git lfs track)
*.pdf filter=lfs diff=lfs merge=lfs -text
*.hex filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.PcbDoc filter=lfs diff=lfs merge=lfs -text
*.SchDoc filter=lfs diff=lfs merge=lfs -text
# 文本文件强制LF换行(跨平台)
*.c text eol=lf
*.h text eol=lf
*.md text eol=lf
# 合并策略(二进制文件不尝试diff,直接标记冲突)
*.pdf merge=binary
*.hex merge=binary
配合GitLab CI检查(防止大文件误提交):
check_lfs:
stage: test
script:
- |
# 检查是否有超过1MB的非LFS文件
find . -type f -size +1M ! -path "./.git/*" | while read file; do
if ! git check-attr filter -- "$file" | grep -q "lfs"; then
echo "ERROR: $file is large but not tracked by LFS"
exit 1
fi
done
allow_failure: false
六、阶段实战:完整的多人协作流程
场景:公司IMU项目,3人团队协作开发v2.0(新增BMI270传感器替换BMI323)。
团队角色:
- 小张(固件组长):负责架构和review
- 小李(驱动工程师):负责BMI270驱动
- 小王(算法工程师):负责传感器融合算法
Day 1:环境准备
# 所有人克隆项目(包含子模块)
git clone --recursive git@gitlab.company.com:firmware/imu-v2.git
cd imu-v2
# 确认远程和分支
git remote -v
git branch -a
Day 2-3:并行开发
# 小李:创建驱动分支
git checkout develop
git pull origin develop
git checkout -b feature/bmi270-driver
# ... 编写驱动代码 ...
git add Drivers/BMI270/
git commit -m "feat(bmi270): add initialization and data read functions
- SPI mode 0, 10MHz
- Verified chip ID 0x24"
git push -u origin feature/bmi270-driver
# 小王:创建算法分支
git checkout develop
git pull origin develop
git checkout -b feature/fusion-algo
# ... 修改融合算法 ...
git add Core/Src/fusion.c
git commit -m "feat(fusion): adapt EKF for BMI270 data format
- Gyro scale factor changed from 16.4 to 32.8 LSB/dps"
git push -u origin feature/fusion-algo
Day 4:代码审查(MR流程)
小李在GitLab发起MR:feature/bmi270-driver → develop
审查者(小张)检查清单:
- 是否修改了共享寄存器?否,仅新增BMI270相关文件
- 是否更新
config.h中的传感器宏?是,#define SENSOR_TYPE BMI270 - 编译是否通过?CI流水线显示✅
- 是否提交.hex?检查Files changed,无编译产物
评论反馈:
Line 45: `HAL_Delay(5)` 可能不满足BMI270上电时序,datasheet要求最小10ms,请修改为10ms并重新测试。
小李修改后push,MR自动更新,小张Approve并合并。
Day 5:集成与发布
# 小张:合并算法分支到develop
git checkout develop
git merge feature/fusion-algo --no-ff
git push origin develop
# 运行CI,确认编译和测试通过
# 打标签发布内部测试版
git tag -a v2.0.0-beta1 -m "Internal beta for HW-v2.0 EVT
- Replace BMI323 with BMI270
- Update sensor fusion EKF
- Tested on 5 EVT boards"
git push origin v2.0.0-beta1
# CI自动触发release阶段,生成HEX并上传到GitLab Release页面
七、团队协作安全守则与灾难恢复
| 灾难场景 | 原因 | 预防措施 | 恢复方法 |
|---|---|---|---|
| 源码仓体积>1GB | 误提交.hex/.bin到普通Git追踪 | .gitignore + LFS + CI检查 |
git filter-repo或BFG Repo-Cleaner清理历史(需团队协调) |
| 子模块HEAD游离 | 进入子模块目录修改后未提交,主仓记录指向不存在commit | 禁止直接修改子模块,或通过subtree管理可修改库 | 手动进入子模块checkout正确commit |
| MR合并后CI失败 | 本地编译通过但CI环境缺少头文件 | 确保CI的Docker镜像与开发环境一致 | Revert合并提交,修复后重新MR |
| 覆盖队友提交 | git push -f或git push --force |
设置GitLab保护分支禁止force push | 通过GitLab Admin或reflog恢复 |
| 敏感信息泄露 | 提交了包含WiFi密码的config.h |
pre-commit钩子扫描敏感字符串 |
git filter-repo移除 + 轮换密码/密钥 |
强制开启GitLab保护:
- Settings → Repository → Protected Branches →
main/develop→ Allow force push: OFF - Settings → Repository → Protected Tags → 仅Maintainers可创建标签
总结与下篇预告
今天我们完成了从本地开发到团队协作的跃迁:
- 远程架构:多远程管理(origin/gitee/backup)+ 裸仓库内网备份,实现代码多副本容灾
- GitLab工作流:共享仓库分支模式适合小团队,MR审查清单强制检查寄存器修改和硬件兼容性
- CI/CD自动化:提交即编译,标签即发布,HEX产物自动关联Git版本号,测试团队可自助下载
- 子模块策略:第三方库用
submodule精确锁定版本,公司内部库用subtree便于修改,避免"更新HAL导致全组编译失败" - 大文件管控:Git LFS管理PDF/HEX/PCB文件,配合
.gitattributes自动拦截,保持源码仓轻量
自检问题:
- 如果你用
git submodule add添加了一个库,然后进入子模块目录git checkout到另一个commit,主仓的git status会显示什么?此时如果你直接git push origin main,队友克隆后子模块会处于什么状态? - CI生成的HEX文件应该存储在Git仓库中吗?如果不应该,测试团队如何获取特定版本的HEX固件?
下篇预告:《【保姆级】Git第五课:救急与高级调试——撤销、恢复与二分查找定位硬件Bug》
将涵盖:
- 撤销与恢复:
git reset(soft/mixed/hard)的本质差异、revert安全撤销已推送提交 - 后悔药:
git reflog找回丢失的commit,即使删除了分支也能恢复 - 二分查找:
git bisect自动化定位引入Bug的提交,结合硬件测试脚本实现"自动找茬" - 补丁传递:
git format-patch/am在无网络环境下传递代码修改
思考题:假设你误将包含公司WiFi密码的config.h提交并push到了GitLab公共仓库,且该提交已被同事拉取。此时单纯git revert是否足够?为什么?正确的补救流程应该是什么?欢迎在评论区讨论。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
分类:嵌入式开发 > 版本控制 > Git
标签:Git远程协作;GitLab工作流;Merge Request;git submodule;Git LFS;CI/CD自动编译;嵌入式团队管理;裸仓库备份;CMSIS版本锁定
更多推荐
所有评论(0)