3. Git核心操作:init、clone、add、commit、status、log 命令详解与实战

好,咱们直接进入正题。Git 这东西,说白了就是嵌入式开发的「后悔药」和「时光机」。我见过太多工程师,代码改了一整天,最后发现还是上个版本好使——可惜没做版本管理,只能重写。嗯,这种痛,经历过一次就够了。

今天咱们就把 Git 最核心的六个命令吃透。你想想看,日常开发中 90% 的场景,其实就靠这几个命令撑着。

3.1 git init:从零开始建仓库

git init 是在本地创建一个新的 Git 仓库。执行后,当前目录下会生成一个隐藏的 .git 文件夹,里面装着版本库的所有元数据。

核心用法:

cd /home/developer/stm32_project
git init

我个人习惯,拿到一个新项目的第一件事就是 git init。哪怕只是写个测试 demo,也先初始化再说。为什么?因为你永远不知道什么时候会改出 bug。

小技巧: 如果你想让默认分支名从 master 改成 main,可以这样:

git init --initial-branch=main

现在很多团队都改用 main 了,入乡随俗嘛。

注意: 不要在已有的 Git 仓库里再执行 git init,除非你确定要重新初始化。我曾经有个同事,在项目根目录不小心又 init 了一次,结果把之前的提交历史全丢了——还好有备份。

3.2 git clone:把远程仓库拉到本地

git clone 是从远程服务器(比如 GitHub、GitLab 或者公司内网)把整个仓库复制到本地。这是团队协作的起点。

git clone https://github.com/example/embedded_project.git
git clone git@github.com:example/embedded_project.git  # SSH 方式,推荐

我建议用 SSH 方式。为什么?因为不用每次 push 都输密码。你想想看,一天 push 几十次,每次都输密码,烦不烦?

克隆完成后,本地会自动关联远程仓库,并且默认分支已经 checkout 好了。直接 cd 进去就能干活。

实战经验: 嵌入式项目往往很大,包含编译器、库文件等。如果只想克隆最新版本,可以加 --depth 1

git clone --depth 1 https://github.com/example/embedded_project.git

这叫「浅克隆」,只拉取最近一次提交,速度飞快。我经常用这个来快速获取别人的代码做参考。

3.3 git status:随时查看仓库状态

git status 是我用得最多的命令,没有之一。它告诉你三件事:哪些文件被改了、哪些文件还没被跟踪、哪些文件已经暂存了。

git status
# 输出示例:
# On branch main
# Changes not staged for commit:
#   modified:   src/main.c
# Untracked files:
#   build/output.bin

嗯,这里要注意:Untracked files 是新文件,Git 还没管它;modified 是已经跟踪过的文件,内容有变动。

我个人习惯,每次 add 之前、每次 commit 之前,都会先跑一遍 git status。说白了,就是确认一下「我要改的东西对不对」。别嫌麻烦,这个习惯能救你很多次。

避坑指南: 我曾经有一次,改完代码直接 git add . 然后 commit,结果把编译生成的 .o 文件和 .bin 文件也加进去了。仓库瞬间大了 200MB。从那以后,我每次都会先看 git status,确认只有源文件被跟踪。

3.4 git add:把改动放进暂存区

git add 是把工作区的改动「暂存」起来,准备提交。它不会直接提交,只是打个标记。

git add src/main.c          # 添加单个文件
git add src/                # 添加整个目录
git add .                   # 添加当前目录所有改动(慎用)
git add -p                  # 交互式添加,只添加部分改动

我最推荐的是 git add -p。这个命令会把每个改动块(hunk)展示给你,问你要不要加。你想想看,有时候一个文件里改了多个功能,但只想提交其中一个——-p 就是干这个的。

实战技巧: 嵌入式开发中,经常会有配置文件(比如 config.h)被不小心改到。用 git add -p 可以只选择你真正想提交的改动,避免把调试用的临时修改也带进去。

3.5 git commit:把暂存区的内容正式存档

git commit 是把暂存区的内容生成一个「快照」,永久保存在仓库里。每个 commit 都有一个唯一的哈希值,可以随时回溯。

git commit -m "fix: 修复 UART 波特率配置错误"
git commit -m "feat: 添加 I2C 驱动支持"

关于 commit message,我有个硬性要求:必须说清楚「为什么改」。不要写 fix bug 或者 update 这种废话。你想想看,三个月后你回来看这段历史,看到 fix bug 能想起什么?什么都想不起来。

推荐格式:

<type>: <简短描述>

<详细说明(可选)>

常用 type:feat(新功能)、fix(修复)、docs(文档)、refactor(重构)、test(测试)。

注意: 不要一次性 commit 太多改动。我见过有人攒了一周的代码,然后一次性 commit,commit message 写了个 update。这种 commit 基本没有回溯价值。建议:一个功能一个 commit,一个 bug 修复一个 commit。

3.6 git log:查看提交历史

git log 是查看仓库的提交历史。默认会显示每个 commit 的哈希值、作者、日期和 message。

git log
# 输出示例:
# commit a1b2c3d4e5f6...
# Author: Zhang San <zhangsan@example.com>
# Date:   Mon Mar 10 14:30:00 2025 +0800
#
#     fix: 修复 SPI 时钟极性配置

我个人最常用的几个变体:

命令 作用
git log --oneline 一行显示一个 commit,简洁明了
git log --graph 显示分支合并图,直观看到分支结构
git log -p 显示每个 commit 的具体改动内容
git log --author="Zhang" 只看某个人的提交
git log --since="2025-01-01" 只看某个时间点之后的提交

实战经验: 当你要排查一个 bug 是什么时候引入的,可以用 git log -p 配合 grep

git log -p --all | grep "波特率"

这样能快速定位到修改过相关代码的 commit。我在项目中用过无数次,非常实用。

3.7 实战:嵌入式项目中的典型工作流

好了,六个命令都讲完了。咱们串起来,看看一个典型的嵌入式开发流程是什么样的:

  1. 拿到项目: git clone git@github.com:company/uart_driver.git
  2. 创建新分支: git checkout -b feature/fix_baud_rate
  3. 修改代码: 编辑 src/uart.c
  4. 查看状态: git status,确认只改了想改的文件
  5. 暂存改动: git add src/uart.c
  6. 提交: git commit -m "fix: 修正 UART 波特率计算误差"
  7. 查看历史: git log --oneline -3,确认提交正确
  8. 推送远程: git push origin feature/fix_baud_rate

核心原则:

  • 每次 add 前先 status
  • 每次 commit 前再 status
  • commit message 写清楚「为什么」
  • 一个 commit 只做一件事

嗯,这六个命令,你只要练熟了,日常开发基本够用。别急着学那些花里胡哨的 rebase、cherry-pick,先把基础打牢。我见过太多人,基础没练好就开始玩高级操作,结果把仓库搞得一团糟。

下一章咱们讲分支管理,到时候你会看到,今天学的这些命令,在分支场景下会发挥更大的作用。