news 2026/10/27 2:02:56

Git学习(1):从零搭建版本控制体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Git学习(1):从零搭建版本控制体系

🔥keyipatience:个人主页

🎬作者简介:C/C++后端开发学习者

🌟专栏传送门:《c++》《linux》《c++高阶数据结构》《c++数据结构与算法》《前端学习》

⭐️patience is key in life

Git 初识

传统保存版本方式的痛点

平时写文档、写代码,很多人靠复制文件 + 改名保存版本:报告-v1、报告-v2、报告-最终版、报告-究极进化版…… 问题: 文件越堆越多 时间久了,记不清每个版本改了哪些内容代码项目同样有这个麻烦。

版本控制器(版本控制系统)

定义:记录工程每一次改动、管理版本迭代、查看文件历史,还支持多人协同开发的系统。

现在最主流的版本控制器:Git

  • Git 可以管理任意格式文件:doc、excel、图纸、代码等
  • 对程序员:核心用途 →管理项目源代码

三、重要注意点

  1. 文本文件(txt、网页、源代码):Git 可以精确跟踪改动 能看到:第几行新增内容、第几行删除内容。
  2. 二进制文件(图片、视频):Git 只能存文件,看不到里面改了什么仅能感知文件大小变化(比如 100KB → 120KB),无法识别图片内部修改。

Linux 下安装 Git

CentOS

1.检查是否已安装

git

提示-bash: git: command not found→ 代表未安装

2. 安装命令

sudo yum -y install git

3.验证 / 查看版本

git --version

Ubuntu

1.检查是否已安装

git

提示Command 'git' not found→ 代表未安装

2. 安装命令

sudo apt install git -y

3.验证 / 查看版本

git --version

创建 Git 本地仓库

仓库(repository):用来做版本控制的文件夹(目录),要管理文件版本,必须先创建仓库。

核心命令:

git init //给【你当前所在的这个文件夹】,装上 Git 版本控制。 //先 cd 进项目目录,再 git init。

输出提示:Initialized empty Git repository in xxx/.git/→ 初始化成功

初始化仓库后自动创建:master主分支 +HEAD指针(HEAD 指向当前所在分支)后面我们会再讲

初始化后变化

执行ll -a可以看到多出.git隐藏目录

.git目录:Git 用来记录、跟踪、管理仓库所有版本信息的核心文件夹,禁止手动修改里面的内容,容易直接损坏 Git 仓库

git 目录内部结构(简要)

.git/ ├── branches ├── config # 当前仓库配置 ├── description ├── HEAD # 指向当前所在分支 ├── hooks # 钩子脚本(提交前后触发脚本) ├── info ├── objects # 存放所有快照、对象(代码版本数据) └── refs ├── heads # 分支引用 └── tags # 标签引用

Git 配置

安装 Git 之后第一件事:配置用户名和邮箱,每次提交记录都会带上这个身份信息

配置命令

# 设置用户名 git config [--global] user.name "Your Name" # 设置邮箱 git config [--global] user.email "email@example.com"

--global重点解释

  • 带--global:全局配置,本机上所有 Git 仓库共用这一套名字 + 邮箱(最常用)
  • 不带--global:仅当前仓库生效,需要先 cd 进入这个 git 仓库目录,适合不同项目用不同身份

2. 查看所有配置

git config -l

3. 删除配置

# 删除用户名配置 git config [--global] --unset user.name # 删除邮箱配置 git config [--global] --unset user.email

工作区、暂存区、版本库

  1. 工作区(Working Directory)你电脑上写代码、放文件的项目文件夹,就是工作区。
  2. 暂存区(stage /index,索引)在.git/index文件里,是一个临时的 “待提交清单”。
  3. 版本库(repository,仓库)就是目录里的隐藏.git文件夹,不属于工作区;Git 就在这里保存所有版本历史,可以回滚、追踪修改。

流转流程

工作区 → git add → 暂存区 → git commit → 版本库(master分支)
  • git add:把工作区的修改,放到暂存区,更新索引
  • git commit:把暂存区里的内容,正式提交写入版本库

添加文件--场景一

git add + git commit + git log

git add:把文件从工作区送到暂存区

三种常用写法:

# 1. 指定单个/多个文件 git add file1 file2 # 2. 添加整个目录(包含里面所有子文件、子目录) git add 目录名 # 3. 【高频】添加当前目录下所有改动的文件 git add .

git commit:把暂存区内容写入版本库(生成一条版本记录)

两种写法:

# 1. 提交暂存区里全部内容(最常用) git commit -m "这里写提交说明" # 2. 只提交暂存区里指定的几个文件 git commit file1 file2 -m "这里写提交说明"

m的含义:message,提交备注,不能省略

作用:写清楚这次改了什么,方便以后看历史、回滚版本,是给自己 / 团队看的。

eg:

git commit -m "commit my first file" git commit -m "add 3 files"

完整实操示例 1(单个文件)

# 1.新建/编辑 ReadMe vim ReadMe # 2.加入暂存区 git add ReadMe # 3.提交到版本库,写备注 git commit -m "commit my first file"

提交成功后,终端输出:1 file changed, 2 insertions(+)含义:1 个文件改动,新增 2 行内容。

完整实操示例 2:多次 add,一次 commit(很常用)

touch file1 file2 file3 # 新建3个文件 git add file1 git add file2 git add file3 git commit -m "add 3 files"

重点:add 可以分开多次执行,文件都堆在暂存区,最后一次 commit 统一存入版本库。

git log:查看提交历史记录

默认

git log

输出内容:

  • commit 一串哈希值:commit id(版本号)
  • Author:提交人(就是前面git config配置的 name 和 email)
  • Date:提交时间
  • 提交 message(自己-m写的那句话)

顺序:最新的提交在最上面,旧的在下面

精简模式(推荐,看日志清爽很多)

git log --pretty=oneline

效果:一行展示一条记录,左边是 commit id,右边是提交备注。

对比:

查看暂存区和版本库文件内容

查看【暂存区】里文件完整内容

git show :文件名 # 例子 git show :ReadMe

:冒号就代表暂存区(index)

查看【版本库(HEAD)】里文件完整内容

git show HEAD:文件名 # 例子 git show HEAD:ReadMe

深入 .git 目录(底层原理)

tree .git //查看整个.git 目录结构

几个核心文件 / 目录

① index

index = 暂存区(stage)git add之后,改动信息就写到这个index文件里。 它保存一份「待提交的文件索引清单」。

② HEAD

HEAD 本质是一个指针文件,记录当前在哪一个分支。

cat .git/HEAD

输出:ref: refs/heads/master意思:HEAD 现在指向master分支。

HEAD 不是直接存 commit id,它先指向分支,分支再指向 commit id。

③ refs/heads/master

cat .git/refs/heads/master

里面存放的就是当前 master 分支最新一条的 commit id(哈希串),master 分支就是靠这个文件记住:我现在停在哪一个版本。

什么是commit id,有什么用?

commit id是SHA1 哈希算法生成的一串十六进制字符串(像:23807c5...56eed6)

  • 每一次git commit,这个文件里的哈希串就会更新成新 commit 的 id
  • 后面回退版本、切换版本,都要用这个 id

存储规则(哈希一共 40 位十六进制):

  • 前 2 位 → 作为文件夹名字
  • 后 38 位 → 作为文件名例:23807c536969cd886c4fb624b997ca575756eed6文件夹名叫23,文件名叫807c536969cd886c4fb624b997ca575756eed6

对象文件是 SHA 压缩加密的,不能直接 cat 打开看,要用专门命命令

git cat-file -p 哈希串 //-p = pretty,格式化打印对象内容

④ objects 目录(Git 对象库,重中之重)

Git 所有版本数据、文件内容、目录结构,全部存在这里。【存放 commit/tree/blob 三类对象】

三个对象各自是干什么的:

  1. blob 对象只保存文件内容,不存文件名、不存路径。 同样内容的不同文件,会复用同一个 blob,省空间。
  2. tree 对象(目录树)代表一个文件夹。 里面记录:这个文件夹下有哪些条目(子文件 / 子目录),每个条目对应:权限、名字、指向 blob 或者子 tree 的哈希。
  3. commit 对象(提交记录)代表一次版本快照(你一次 git commit)。 里面记录:
  • 一个 tree 的哈希(这次提交对应的顶层目录树)
  • parent:上一个 commit 的哈希(形成版本链)
  • author、committer、提交备注-m "xxx"

三者的引用关系

commit 对象 ↓(持有一个tree哈希,找到tree对象) tree 对象 ↓(持有若干哈希,找到blob或者子tree对象) blob 对象 或者 子tree对象

eg:

commit(23807c...) └── tree(830a8c...) ├── blob(9c9e1f...) → ReadMe 的内容 ├── blob(e60de2...) → file1 的内容 ├── blob(e60de2...) → file2 的内容 └── blob(e60de2...) → file3 的内容

完整大图

HEAD (.git/HEAD) ↓ 指向分支引用 refs/heads/master ↓ 里面存最新commit id commit 对象 (在objects里) ↓ 记录顶层tree哈希 tree 对象 (在objects里) ↓ 记录多个blob/子tree哈希 blob / tree 对象 (都在objects里)

打印看一看:

//(1)commit 对象(提交对象) git cat-file -p 23807c536969cd886c4fb624b997ca575756eed6 //输出内容: tree 830a8c9feefbdc098bbae2cdc25e5034ce1920d7 parent c61428926f3853d4ec6dde984415b0e6c1dabcc6 author hyb01 <2689241679@qq.com> ... committer hyb01 <2689241679@qq.com> ... add 3 files //(2)tree 对象 git cat-file -p 830a8c9feefbdc098bbae2cdc25e5034ce1920d7 //输出类似: 100644 blob 9c9e1f0f6bff3015df71a0063004476f5e6cfd54 ReadMe 100644 blob e60de26bb2d1d6434b8b29ae775ad8c2e48c5391 file1 100644 blob e60de26bb2d1d6434b8b29ae775ad8c2e48c5391 file2 100644 blob e60de26bb2d1d6434b8b29ae775ad8c2e48c5391 file3 //(3)blob 对象 git cat-file -p 9c9e1f0f6bff3015df71a0063004476f5e6cfd54 //直接输出文件原始内容: hello bit

一句话流程复盘

修改工作区文件 → git add:生成 blob 存入 objects、更新 index 暂存区 → git commit:生成 commit 对象 + tree 对象,更新 master 分支记录。

添加文件--场景二

git status + git diff

Git 跟踪的是修改,不是整个文件。新增一行、删除一行、改动字符、新建文件,全都算一次修改。

git status 查看仓库状态

git status

告诉你:工作区、暂存区里面文件处于什么状态。

第一种输出(修改了文件,但还没 git add)

含义: 文件已经在工作区改动还没有加入暂存区提示给你两个选择:

  • git add <file>:把改动加入暂存区
  • git restore <file>:扔掉工作区改动,恢复原样

第二种输出(已经 git add,在暂存区等待 commit)

含义:修改已经放到暂存区,准备提交 提示:git restore --staged <file>可以把文件从暂存区撤出来(取消 add)

第三种输出(commit 完成之后)

含义:暂存区空、工作区干净,当前没有未提交改动

git diff 查看具体差异(看改了啥)

git diff [文件名]

git diff ReadMe

工作区 vs 暂存区 → 看add 之后又改了、还没再次 add的改动

diff 格式解读(Unix 标准 diff):

diff --git a/Readme b/Readme # git格式diff,a是旧版(暂存区),b是新版(工作区) index c940fc8..3d025e4 100644 # c940fc8旧blob哈希,3d025e4新blob哈希;100644普通文件权限 --- a/Readme # --- 代表旧版本 +++ b/Readme # +++ 代表新版本 @@ -1,2 +1,3 @@ # -1,2:旧片段从第1行,共2行;+1,3:新片段从第1行,共3行 hello world # 无标记:新旧版本都存在,该行不变 hello git # 无标记:新旧版本都存在,该行不变 +hello ysm # + 加号:新版本新增这一行

git diff HEAD -- [文件名]

git diff HEAD -- ReadMe

对比:版本库(HEAD 指向的最新 commit) VS 工作区不管有没有 add,都能看到和上一次提交相比,一共改了哪些东西(commit肯定就看不到了)

git diff --cached--[文件名]等价git diff --staged

暂存区 vs HEAD(版本库)→ 马上要 commit 提交的内容!

版本回退

回退核心本质:git reset移动HEAD 和分支指针(master),指向历史上某个 commit; 三个参数的区别,就是【暂存区、工作区】要不要跟着一起改动。

先记住一条主线例子: 连续提交 3 次:version1 → version2 → version3

commit1(version1) ← commit2(version2) ← commit3(version3, HEAD/master现在指向

三个参数

git reset [--soft | --mixed | --hard] 目标commit
参数版本库(HEAD / 分支指针)暂存区(index)工作区特点
--soft✅ 回退到目标 commit❌ 不变❌ 不变只挪指针;改动还在暂存区,可以直接 commit
--mixed(默认,不加参数就是它)✅ 回退到目标 commit✅ 重置成目标版本❌ 不变改动从暂存区退回工作区,状态是 modified
--hard✅ 回退到目标 commit✅ 重置成目标版本✅ 重置成目标版本危险!工作区直接覆盖,未保存代码丢失(git reflog找回)

简写写法(定位要回退到哪一个版本)

  • HEAD:当前最新版本
  • HEAD^:上 1 个版本
  • HEAD^^:上 2 个版本
  • HEAD~1= HEAD^,上一个
  • HEAD~2= HEAD^^,上两个
  • 注意:都是相对于 HEAD 当前指向的这个 commit往上数。
  • 分不清楚也可以直接写完整 / 部分 commit id(只要前缀唯一就行,比如 d95c13f)

举例:git reset --hard HEAD^回退到上一个版本

怎么知道现在处于哪个版本?

看当前 HEAD / 分支指向(最常用)

git log --pretty=oneline

第一行开头就是当前 commit id,括号里HEAD -> master代表现在就在这条提交上。

一个巨大问题:reset --hard 之后,git log 看不到被丢掉的 commit 了!

例子:reset --hard 回到 version2

git log 里不再出现 version3 那条 commit,好像 version3 消失了。 这时你后悔了,想回到 version3 怎么办?

git reflog

git log:看分支提交链上的历史(reset 之后旧 commit 不在链上,就不显示)

git reflog:记录本地 HEAD 所有移动记录!不管你 reset、切换分支,HEAD 每一次挪动都会被记下来,是本地的操作日志。

输出示例:

d95c13f HEAD@{1}: commit: add version3 14c12c2 HEAD@{2}: commit: add version2 cff9d1e HEAD@{3}: commit: add version1

这里d95c13f就是消失的 version3 的 commit id! 拿到这个 id,就可以再次 reset 回去:

git reset --hard d95c13f

就救回 version3 了。

完整实例:

# 1. 新建仓库(如果还没有) mkdir testgit && cd testgit git init # 第1次提交 version1 echo "hello version1" > ReadMe git add ReadMe git commit -m "add version1" # 第2次提交 version2 echo "hello version2" >> ReadMe git add ReadMe git commit -m "add version2" # 第3次提交 version3 echo "hello version3" >> ReadMe git add ReadMe git commit -m "add version3" git log --pretty=oneline 输出类似: a3c3 (HEAD -> master) add version3 b721 add version2 58de add version1 //案例 1:--hard git reset --hard HEAD^ # 看文件内容 cat ReadMe # 看日志 git log --pretty=oneline //现象: - ReadMe 里面只有 version1、version2,version3 不见了 - log 里看不到 v3 的那条记录了 - HEAD 现在指向 v2 //后悔了!想找回 v3: git reflog //输出: a3c3 HEAD@{1}: commit: add version3 b721 HEAD@{0}: reset: moving to HEAD^ //HEAD@{0}= 现在,HEAD@{1}= 上一步,数字越大越早 //拿到 v3 的 id `a3c3`,切回去: git reset --hard a3c3
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 2:02:56

从一张学生表到 Fiori 应用,我用 Managed RAP 跑通了一个完整的 Student Management Application

在 Eclipse ADT 里按下 Ctrl + F3,看着一个刚创建的 ZSTD_TABLE_DEMO 被激活时,这个应用其实还远远称不上一个真正的 SAP RAP Application。 那时数据库里只有一张很简单的学生表,里面保存学生姓名、班级、年龄、学校名称几个字段。真正让我开始理解 RAP 的,不是把这张表建…

作者头像 李华
网站建设 2026/10/27 2:02:01

关卡数据问题:出生点坐标拆包报错看不懂?新手一步步排查

大家好&#xff0c;我是 SiKi老师。关卡工具读出生点坐标&#xff0c;代码里一句 x, y, z pos&#xff0c;跑到一半抛出 not enough values to unpack&#xff0c;却看不出是哪一条记录出了问题。先别急着在外面套 try&#xff0c;我会先在拆包之前检查长度和类型&#xff0c;…

作者头像 李华
网站建设 2026/10/27 2:01:37

FreeRTOS——什么是任务切换

任务切换的核心 1.什么是任务切换 任务切换概念 单片机正常情况下只有一个主程序在跑。在引入FreeRTOS之后&#xff0c;系统会有多个任务&#xff0c;每个任务都像一段独立的小程序&#xff0c;有自己的栈空间&#xff0c;自己的执行现场。 但CPU同一时刻只能执行同一个任务。所…

作者头像 李华
网站建设 2026/10/27 2:01:24

07-06-源码-.NET Core GC的极致优化技术

.NET Core GC 的极致优化技术篇章&#xff1a;07-源码深度-.NET Core GC | 阅读时间&#xff1a;约 40 分钟一、引言.NET Core GC 的极致性能不仅来自高级算法&#xff0c;还来自大量底层的微优化技术。每项微优化单独看可能只提升 1-5%&#xff0c;但累积起来产生了巨大的性能…

作者头像 李华
网站建设 2026/10/27 2:00:36

ATMEL 单片机新手入门与快速上手指南

摘要:本文面向零基础嵌入式开发者,以 ATMEL 系列单片机为对象,完整梳理从入门到上手的实战路径。内容涵盖芯片核心特点与应用场景、开发环境与工具链安装、最小系统电路连接、LED 闪烁程序编写与烧录、GPIO 输入输出控制、定时器中断、串口通信、常见编译报错排查、仿真器调…

作者头像 李华
网站建设 2026/10/27 2:00:17

Modbus 通信从入门到实战:RTU、TCP、寄存器地址与 C# 解析一次讲透

一句话理解&#xff1a; Modbus 就像设备之间约定好的一套“问答规则”——上位机按照规则询问温度、压力或设备状态&#xff0c;仪表、PLC 等设备再按照规则返回数据。真正难的不是“发几个字节”&#xff0c;而是弄清楚读哪个地址、用什么功能码、数据如何解释&#xff0c;以…

作者头像 李华