3. Git基础操作:从初始化到规范提交

好,咱们今天聊聊Git最基础的操作。说实话,我见过太多嵌入式工程师把Git当“备份工具”用——每天下班前commit一下,完事。这其实挺可惜的。Git真正的威力,在于它能让你的版本管理变得像精密仪器一样可控。

我个人习惯,在开始一个新嵌入式项目时,第一件事就是初始化Git仓库。别等到代码写了一半才想起来版本控制,那时候已经晚了。

3.1 git init 与 git clone:两种开始方式

git init 是在本地创建一个全新的仓库。适合你从零开始写项目。

cd my_embedded_project
git init

执行完这条命令,当前目录下会多出一个 .git 文件夹。嗯,别手贱去删它,那是Git的心脏。

git clone 则是从远程复制一个已有仓库到本地。我在接手团队遗留项目时经常用这个。

git clone https://github.com/example/stm32-firmware.git

这里有个小坑:嵌入式项目往往包含大尺寸的二进制文件(比如芯片的固件库、编译中间产物)。我曾经克隆一个仓库,结果发现下载了2个多G——后来才知道,有人把编译生成的 .hex 文件也提交上去了。所以,后面我们会讲 .gitignore 怎么配置,提前规避这类问题。

3.2 git add 与 git commit:把代码“装进”版本库

很多新手搞不清 addcommit 的关系。我打个比方:git add 是把文件放进“待提交区”(暂存区),git commit 才是正式拍照存档。

# 添加单个文件
git add main.c

# 添加所有改动(慎用!)
git add .

# 提交并写信息
git commit -m "fix: 修复UART接收缓冲区溢出问题"

我个人建议,尽量别用 git add . 一把梭。为什么?因为有时候你改了几个文件,但只想提交其中一部分。用 git add 逐个添加,能让你更清楚自己在做什么。

小技巧: 如果你只想提交某个文件的部分改动(比如只提交某个函数修改,不提交同一文件里的调试代码),可以用 git add -p。它会逐块询问你是否要暂存。这个功能我在调试嵌入式驱动时经常用。

3.3 git status 与 git log:随时掌握仓库状态

git status 是我用得最频繁的命令,没有之一。每次提交前,我都会先跑一遍,看看哪些文件改了、哪些还没跟踪。

git status

输出会告诉你三件事:

  • 已暂存(Staged)—— 准备提交的
  • 已修改未暂存(Modified)—— 改了但还没add的
  • 未跟踪(Untracked)—— 新文件,Git还没管它

git log 则是查看提交历史。我习惯加上 --oneline 参数,让输出更简洁。

git log --oneline -5

这会显示最近5次提交,每条一行。你想想看,如果每次提交信息都写得乱七八糟,那这个log基本就没法看了。所以,提交信息的规范写法,我们后面重点讲。

3.4 git diff:看看你到底改了啥

有时候你改了一堆代码,但忘了具体改了哪些地方。这时候 git diff 就派上用场了。

# 查看未暂存的改动
git diff

# 查看已暂存的改动(跟上次提交比)
git diff --staged

我记得有一次,同事说“我就改了一行配置”,结果我一看diff,他改了整整一个头文件。所以,提交前用 git diff --staged 检查一下,能避免很多乌龙。

3.5 .gitignore 文件配置:别把垃圾也提交了

嵌入式项目里,有很多文件是不应该进版本库的:

  • 编译产物:.o、.hex、.bin、.elf
  • IDE配置文件:.idea、.vscode、*.uvguix.*
  • 临时文件:*.log、*.bak、*.swp
  • 第三方库的二进制包

一个典型的嵌入式项目 .gitignore 长这样:

# 编译输出
build/
*.o
*.hex
*.bin
*.elf
*.map

# IDE配置
.idea/
.vscode/
*.uvguix.*

# 系统文件
.DS_Store
Thumbs.db

# 日志
*.log
注意: .gitignore 只对“未跟踪”的文件有效。如果一个文件已经被Git跟踪了,你再把它加到 .gitignore 里是没用的。我曾经踩过这个坑——把编译输出目录加到 .gitignore 后,发现它还在被跟踪。后来才想起来,之前已经提交过了。解决办法是用 git rm --cached 先把它从跟踪列表里移除。

3.6 提交信息的规范写法:让历史可读

这是很多嵌入式工程师容易忽略的地方。我见过太多“update”、“fix bug”、“改了点东西”这样的提交信息。说实话,三个月后你自己都看不懂当时改了啥。

我推荐使用 Conventional Commits 规范,格式如下:

<type>: <简短描述>

<详细说明(可选)>

常用的 type 包括:

类型 含义 嵌入式场景举例
feat 新功能 feat: 添加SPI Flash驱动
fix 修复bug fix: 修复看门狗超时导致系统重启
docs 文档 docs: 更新I2C通信协议说明
refactor 重构 refactor: 重构GPIO初始化代码
perf 性能优化 perf: 优化ADC采样率,降低CPU占用
test 测试 test: 添加UART回环测试用例

举个例子,一个规范的提交信息:

fix: 修复CAN总线在高速率下丢帧问题

问题原因:接收FIFO溢出时未及时清空标志位
解决方案:在中断服务函数中增加FIFO溢出检测与恢复逻辑
影响范围:仅影响CAN2通道,CAN1不受影响
我的经验: 提交信息的第一行不要超过50个字符。为什么?因为很多Git工具(比如git log --oneline)只显示第一行。如果第一行写不下,就写个概括,然后在正文里展开。

3.7 嵌入式场景下的Git操作建议

最后,分享几个我在嵌入式项目中积累的小习惯:

  1. 每次提交只做一件事。 修复bug就只提交bug修复,不要混着加新功能。这样万一要回退,不会牵连其他改动。
  2. 提交前编译一下。 我见过有人提交了编译不过的代码,结果整个团队都被卡住。养成习惯:commit前先 make clean && make
  3. 二进制文件单独管理。 芯片的固件库、工具链这些大文件,别往Git里塞。用包管理器或者单独的文件服务器管理。
  4. 分支命名要有意义。 比如 fix/can-bus-overflowfeature/adc-dma-support,别用 test1new_branch 这种。

好了,Git基础操作就讲到这里。下一章我们会聊分支管理——说白了,就是怎么让多个人同时开发,还不打架。