版本控制基础:Git 核心概念与工作流程

版本控制这件事,说白了就是给代码拍快照。你每改一次代码,Git 就帮你存一张照片,哪天改崩了,随时能翻出老照片恢复。我在智能座舱项目里见过太多人——包括我自己早期——把代码到处复制备份,什么「final_v3」、「真的最终版_v5」,最后自己都分不清哪个是哪个。

嗯,咱们今天就把 Git 的核心概念掰开揉碎讲清楚。你理解了这几个东西,后面做版本发布就顺了。

仓库:你的代码保险箱

仓库(Repository)就是 Git 用来存代码和所有历史记录的地方。分两种:

  • 本地仓库:在你电脑上,离线也能用
  • 远程仓库:在服务器上,团队共享

我建议座舱项目一开始就建好远程仓库。别等代码写了几万行再推,那时候冲突能让你怀疑人生。

一句话记住:仓库 = 你的代码 + 所有历史版本 + 分支 + 标签。删了本地仓库,只要远程还在,就能拉回来。

提交:最小粒度的快照

提交(Commit)是 Git 最核心的操作。每次提交就是一次「我确认这段代码没问题了」的标记。

每个提交包含:

  • 一个唯一的 SHA-1 哈希值(40 位十六进制,像指纹)
  • 提交者信息(谁、什么时间)
  • 提交信息(你写的备注)
  • 指向父提交的指针

我在项目中吃过一次亏:提交信息写「fix bug」,两周后回来看,根本不知道修了哪个 bug。后来我强制团队用 type(scope): description 格式,比如 fix(display): fix brightness not saving after reboot。你想想看,这样是不是一眼就知道改了啥?

我的习惯:每次提交只做一件事。修复一个 bug 一个提交,加一个新功能一个提交。别攒一堆一起提交,review 的时候 reviewer 会骂娘的。

分支:平行宇宙

分支(Branch)让你能在不影响主线的情况下做实验。座舱项目里,我经常同时维护三个分支:

分支类型 用途 谁在用
main 生产就绪代码 所有开发者
develop 日常开发集成分支 开发团队
feature/xxx 单个功能开发 个人

分支切换的原理其实很简单:Git 只是移动一个指针。你切到 feature/night-mode,工作目录里的文件就变成那个分支的样子。切回来,文件又变回 main 的样子。

我曾经踩过的坑:在 main 分支上直接改代码。改到一半发现要修另一个紧急 bug,但改动还没提交,切不了分支。最后只能 git stash 暂存,修完 bug 再 pop 出来。从那以后,我绝不在 main 上直接改代码。

标签:给历史打桩

标签(Tag)就是给某个提交起个有意义的名字。座舱项目发布版本时,我必打标签:

git tag -a v2.1.0 -m "Release version 2.1.0 - Night mode + OTA fix"
git push origin v2.1.0

标签和分支的区别:标签是只读的,不能在上面改代码。分支是可以移动的指针。我习惯用语义化版本号:v主版本.次版本.补丁。

Git 工作流程:日常操作闭环

咱们座舱项目一天的工作流程,我画了个图:

Git 日常工作流程 Git 日常开发工作流程 工作区 (Working) 暂存区 (Staging) 本地仓库 (Local) 远程仓库 (Remote) git add git commit git push git pull / git fetch 日常闭环:修改 → git add → git commit → git push → 团队协作 → git pull 同步 分支管理:feature 分支开发 → 合并到 develop → 提 PR → review → 合并到 main

你看这个流程,其实就三步:改代码 → 暂存 → 提交。推送到远程是团队协作时才需要。

Git 常用命令:够用就行

Git 命令几百个,但日常用的就十来个。我列了个清单,你照着用就行:

场景 命令 说明
初始化 git init 在当前目录创建仓库
克隆 git clone <url> 从远程拉取完整仓库
查看状态 git status 看哪些文件改了、哪些暂存了
暂存 git add <file> 把改动加入暂存区
提交 git commit -m "msg" 把暂存区内容生成一个提交
推送 git push 把本地提交推送到远程
拉取 git pull 拉取远程最新代码并合并
分支 git branch <name> 创建分支
切换 git checkout <branch> 切换到指定分支
合并 git merge <branch> 把指定分支合并到当前分支
查看日志 git log --oneline 简洁版提交历史
打标签 git tag -a v1.0 -m "msg" 给当前提交打标签

我的小技巧:把 git log --oneline --graph --all 设成别名 git tree。这样看分支结构一目了然,座舱项目几十个分支的时候,这个命令救过我很多次。

避坑指南:我踩过的三个坑

  1. 合并冲突不会处理:有一次座舱的 HMI 团队和底层驱动团队同时改了同一个文件,合并时冲突了。我当时的做法是:git mergetool 打开可视化工具,逐行对比,保留需要的代码。别怕冲突,冲突是正常的,关键是别乱删别人的代码。
  2. 提交信息太随意:我见过最离谱的提交信息是「asdf」。后来我定了个规矩:提交信息必须说明「为什么改」而不是「改了啥」。比如 fix: increase touch debounce time to prevent false triggers,这样 reviewer 才知道你的意图。
  3. 忘记拉取就推送:你改了一上午代码,git push 的时候提示「远程有更新,请先拉取」。这时候别用 --force!先 git pull --rebase,把你的提交放在远程提交后面,再推送。我见过有人 force push 把同事的代码覆盖了,那场面……嗯,很尴尬。

重要提醒:永远不要在 main 或 develop 分支上直接 git push --force。如果你不确定自己在做什么,先问团队里经验丰富的人。座舱项目是车规级软件,一个错误的 force push 可能导致整个发布流程回滚。

好了,Git 核心概念就这些。你先把仓库、提交、分支、标签这四个概念吃透,后面的工作流程和命令自然就顺了。记住:Git 不是用来折磨你的,它是帮你管理代码历史的工具。用好了,它能让你在座舱项目里游刃有余。