git原理浅析

news2024/11/15 11:33:50

1.git概念

在这里插入图片描述

我们的项目一般由文件夹和文件组成,在文件系统中,基本都是树形结构, 在git中,文件夹称为 “tree” ,文件称为 “blob” ,顶层文件夹称为 “top-level tree” 。下方的目录结构是个例子而已:

. (top-level tree)
├── humx.txt (blob,内容为“111”)
└── test (tree)
    └── humx1.txt (blob,内容为“222”)
    └── humx2.txt (blob,内容为“222”)

整个树形结构我们称为"commit", 在git 系统中, 就是众多commit构成的

11316@DESKTOP-SMV4E4J MINGW64 /f/idea
$ mkdir test

11316@DESKTOP-SMV4E4J MINGW64 /f/idea
$ cd test

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test
$ git init
Initialized empty Git repository in F:/idea/test/.git/

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ cd .git/

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test/.git (GIT_DIR!)
$ tree
.
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- info
|   `-- exclude
|-- objects
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    `-- tags


.git目录下结构功能:

  • HEAD 文件:指向当前所在分支。
  • config文件:包含了一些git的配置。
  • description文件:只有在GitWeb项目中才会用到,所以不用关注这个文件。
  • hooks文件夹:包含了一些钩子脚本, 触发某些特定事件触发
  • info文件夹:包含了.gitignore 文件中的信息, 忽略某些文件用的
  • objects文件夹:存放object的数据库,存放整个项目的所有数据。
  • refs文件夹:存放了指向objects的指针(如branches,tags,remotes等)

首先,我们先创建一个文件humx.txt 并写入111的内容,并执行git add ,得出以下:

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ echo '111' > humx.txt

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ git add .
warning: LF will be replaced by CRLF in humx.txt.
The file will have its original line endings in your working directory

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ tree .git/
.git/
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- objects
|   |-- 58
|   |   `-- c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    `-- tags

可以看到,在objects文件夹下多了一个58文件夹和一个名叫c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c文件,把两者看成一个整体就是一个git object,而且我们将它们的名字拼接起来就能得到一个40位的hashId,这个hashId是这个object的唯一标志符,git通过这个hashId来查找这个object。不过不能直接cat,因为文件是经过压缩的,不能直接阅读。通过 git cat-file命令查看可得到 111 的内容 和blob 的类型。并且多了index文件,这是我们git 的暂存区存放的文件,内容为(mode) (object) (stage) (file).

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ git commit -m"first commit"
[master (root-commit) a4f7afb] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 humx.txt

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ tree .git/
.git/
|-- COMMIT_EDITMSG
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           `-- master
|-- objects
|   |-- 56
|   |   `-- 63e48c7b2bc80c2cdc2990d11ba8594a87ba0f
|   |-- 58
|   |   `-- c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c
|   |-- a4
|   |   `-- f7afb5eda5f66b249171a744feebf9a754a7ea
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    |   `-- master
    `-- tags

接下来提交文件,我们发现又多了两个object,其中:
56:(tree)
在这里插入图片描述
a4:(commit)
在这里插入图片描述
仔细观察,commit指向tree, tree指向blob,可以得出:
在这里插入图片描述

然后在创建一个test文件夹,文件夹下新建humx1.txt humx2.txt 内容分别为222 333

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test/text (master)
$ echo '222' > humx1.txt

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test/text (master)
$ echo '333' > humx2.txt

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test/text (master)
$ cd ..

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ git add .
warning: LF will be replaced by CRLF in text/humx1.txt.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in text/humx2.txt.
The file will have its original line endings in your working directory

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ git commit -m"second commit"
[master 8b2580a] second commit
 2 files changed, 2 insertions(+)
 create mode 100644 text/humx1.txt
 create mode 100644 text/humx2.txt

11316@DESKTOP-SMV4E4J MINGW64 /f/idea/test (master)
$ tree .git/
.git/
|-- COMMIT_EDITMSG
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           `-- master
|-- objects
|   |-- 30
|   |   `-- ed92ac0fa69377e0f25cb339e1e5676a300c5a
|   |-- 55
|   |   `-- bd0ac4c42e46cd751eb7405e12a35e61425550
|   |-- 56
|   |   `-- 63e48c7b2bc80c2cdc2990d11ba8594a87ba0f
|   |-- 58
|   |   `-- c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c
|   |-- 8b
|   |   `-- 2580a781611d1e7be39e42ab8bbf88181103bf
|   |-- a4
|   |   `-- f7afb5eda5f66b249171a744feebf9a754a7ea
|   |-- c2
|   |   `-- 00906efd24ec5e783bee7f23b5d7c941b0c12c
|   |-- df
|   |   `-- 15a9f7eb285f1384886435bf4055f12d1bb93a
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    |   `-- master
    `-- tags

30:(tree)
在这里插入图片描述
55:(blob)
在这里插入图片描述
8b:(commit)
在这里插入图片描述
c2:(blob)
在这里插入图片描述
df:(tree)
在这里插入图片描述
我们可以发现:hashId为df的tree是新生成的,是因为根目录下的文件/文件夹列表发生了变化。git并没有直接在56 的tree中直接修改,是因为如果我们需要跳回第一次commit的内容时,直接使用56的tree就可以了,这样就很方便。
还有值得注意的是:由于humx.txt文件内容未改变,df tree直接引用了58这个object,这样的策略可以为.git目录节省很大的空间,如下图:
在这里插入图片描述

2.Reference

git是通过hashId来查找某个commit的,这对于计算机来说是件非常简单的事,但对于人来说,要记住这么长的hashId,真不是件容易的事。如果能给这些hashId取一些“简单的名字”(比如master、dev、HEAD等),那就非常容易记忆了。在git术语中,这些“简单的名字”被叫做 “reference” 。这些reference主要保存在.git/refs文件夹中

2.1 Branch
这里我们新建一个名为test1的仓库,并创建humx3.txt文件,进行commit后,cd 到.git/refs/head路径下,会有一个master文件,直接查看文件可以得到这个commit的hashId,可以直接找到这个提交,下面清楚的标记了这次提交的 tree ,作者信息,并且类型为 commit。git管理的项目原本没有master分支,当我们提交第一个commit后,git会自动给我们创建master分支,并将它指向第一个commit。
在这里插入图片描述

.
|-- COMMIT_EDITMSG
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           `-- master
|-- objects
|   |-- ce  
|   |   `-- 013625030ba8dba906f756967f9e9ca394464a
|   |-- e2
|   |   `-- 244575c8f723ffb6de45fac2b34391cc1b074d
|   |-- fb
|   |   `-- e2b124907eb30c097cec796f60dfb9c18df8ff
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    |   `-- master
    `-- tags

ce:
在这里插入图片描述

e2:
在这里插入图片描述

fb:
在这里插入图片描述
在这里插入图片描述
这里我们修改一下开始文件的内容,追加“world”进去,发现新的提交指向了新的地址,但文件名还是之前的文件名。
在这里插入图片描述

.git/
|-- COMMIT_EDITMSG
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           `-- master
|-- objects
|   |-- 47
|   |   `-- 0b84f11fafd7e2a29a54d9cefd9fa199b9f3d3
|   |-- 94
|   |   `-- 954abda49de8615a048f8d2e64b5de848e27a1
|   |-- b7
|   |   `-- e48a1342abdc6c13ff4c10993625d6a60d836e
|   |-- ce
|   |   `-- 013625030ba8dba906f756967f9e9ca394464a
|   |-- e2
|   |   `-- 244575c8f723ffb6de45fac2b34391cc1b074d
|   |-- fb
|   |   `-- e2b124907eb30c097cec796f60dfb9c18df8ff
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    |   `-- master
    `-- tags

47:
在这里插入图片描述

94:
在这里插入图片描述

b7:
在这里插入图片描述

接下来,我们在切换分支,并新增humx4.txt文件写入内容hahaha
在这里插入图片描述

.git/
|-- COMMIT_EDITMSG
|-- HEAD
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg.sample
|   |-- commit-msg.sample
|   |-- fsmonitor-watchman.sample
|   |-- post-update.sample
|   |-- pre-applypatch.sample
|   |-- pre-commit.sample
|   |-- pre-push.sample
|   |-- pre-rebase.sample
|   |-- pre-receive.sample
|   |-- prepare-commit-msg.sample
|   `-- update.sample
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|       `-- heads
|           |-- master
|           `-- text
|-- objects
|   |-- 44
|   |   `-- 5a69c00e48288ac420a2ead9ae5a1cb4cd36d4
|   |-- 47
|   |   `-- 0b84f11fafd7e2a29a54d9cefd9fa199b9f3d3
|   |-- 94
|   |   `-- 954abda49de8615a048f8d2e64b5de848e27a1
|   |-- b7
|   |   `-- e48a1342abdc6c13ff4c10993625d6a60d836e
|   |-- bf
|   |   `-- 06cff14be1e67be65b50f333cbf1d13270662e
|   |-- ce
|   |   `-- 013625030ba8dba906f756967f9e9ca394464a
|   |-- dc
|   |   `-- 55dcba685e66992a5379e393a4fb2de1738d92
|   |-- e2
|   |   `-- 244575c8f723ffb6de45fac2b34391cc1b074d
|   |-- fb
|   |   `-- e2b124907eb30c097cec796f60dfb9c18df8ff
|   |-- info
|   `-- pack
`-- refs
    |-- heads
    |   |-- master
    |   `-- text
    `-- tags

44:
在这里插入图片描述
bf:
在这里插入图片描述
dc:
在这里插入图片描述
在这里插入图片描述

HEAD文件保存着当前所在分支的路径,git通过这个路径访问到对应分支文件,然后通过这个分支文件保存的hashId就能获取到对应commit,这样git就能构建出当前commit对应的目录结构,如图:
在这里插入图片描述

3.总结

  • objects文件夹是git最重要的数据库,所有的文件内容,及各个版本的内容,都保存在objects文件夹中。
  • objects文件夹中主要保存三类object:commit、tree、blob,它们都由一个文件夹和文件组成,文件夹和文件的名字拼接成40位的hashId,这个hashId就是这个object的唯一标识符,git通过这个hashId来查找某个object。另外,这些文件都是经过压缩的,不能直接供人阅读,需要通过git cat-file指令查看。
  • 每一个commit都对应一个top-level tree,以top-level tree为根节点,可以构造出当前版本的目录结构,通过访问blob类的object,就能读取到对应文件的具体内容。另外,多个版本之间的文件如果是完全相同的,git只会生成一个blob对象,多个版本引用同一个blob对象,这可以大大节省磁盘空间。
  • referrence都是基于commit来实现的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/64714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Global Mapper栅格计算器,波段计算NDVI、NDSI、NDWI等

Global Mapper栅格计算器,波段计算NDVI、NDSI、NDWI等1. Global Mapper中的栅格计算器2. 查看数据属性,检查波段数量3. 打开栅格计算器,进行波段计算Global Mapper功能丰富,其栅格计算器工具内置很多遥感指数,方便进行…

TwineCompile高级编译系统

TwineCompile高级编译系统 TwineCompile是我们对C编译速度慢的解决方案。通过使用多线程、文档缓存和自动化后台编译技术,集成到CBuilder IDE中,大大降低了编译/制作/构建的次数。 TwineCompile是一个创新的电子书系统,它利用多线程工程和缓存…

Java项目:SSM学生选课管理系统

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 由SpringMVCMyBatis为主要框架,mysql8.0配置主从复制实现读写分离。前端主要由bootstrap完成,背景用particles.js插件。…

Spring Boot整合JWT实现用户认证

初探JWT 什么是JWT JWT(Json Web Token),是一种工具,格式为XXXX.XXXX.XXXX的字符串,JWT以一种安全的方式在用户和服务器之间传递存放在JWT中的不敏感信息。 为什么要用JWT 设想这样一个场景,在我们登录一个网站之后&#xff0…

[Cortex-M3]-2-map文件解析

目录 1 几个问题 1.1 什么是map文件 1.2 如何查看编译出的程序和数据的信息 1.3 如何生成map文件 1.4 map文件里面有哪些信息 2 map文件信息详解 2.1 Section Cross References 2.2 Removing Unused input…

15年磨一剑,亚马逊云科技数据产品掌门人 Swami 揭秘云原生数据战略的三大关键要素

2022亚马逊云科技 re:Invent 全球大会正在拉斯维加斯如火如荼进行中,亚马逊云科技数据与机器学习副总裁 Swami Sivasubramanian 博士发表了“数据与机器学习如何助力企业构建端到端的数据战略”的主题演讲来开启第三天的日程。 Swami 博士重点介绍了亚马逊云科技在…

玉米脱粒机设计全套

目 录 摘要 I Abstract II 1引言 1 1.1 课题的来源与研究的目的和意义 1 1.2 本课题研究的内容 3 2玉米脱粒机总体结构的设计 5 2.1 玉米脱粒机工作方式的选择 7 2.2 玉米脱粒机的结构原理 10 2.3 机械传动部分的设计计算 11 2.3.1电机的选型计算 12 2.3.2 V带传动的设计计算 1…

C语言:文件操作(2)

文件的打开和关闭 文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。 在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。 ANSIC规定使用fopen函数来打开文…

(十五) 共享模型之工具【线程池】

一、自定义线程池 1. 简易线程池 Slf4j(topic "c.TestPool") public class TestPool {public static void main(String[] args) {ThreadPool threadPool new ThreadPool(2,1000, TimeUnit.MILLISECONDS, 10);for (int i 0; i < 5; i) {int j i;threadPool.exe…

博球一看,记录疯狂!我与世界杯的那些二三事

文章目录 &#x1f525;关于世界杯 &#x1f525;关于2022卡塔尔世界杯 &#x1f525;我与足球 &#x1f525;我与世界杯 ⚽分享一颗足球 ⚽实现效果 &#x1f525;关于世界杯 大力神杯 国际足联世界杯&#xff08;FIFA World Cup&#xff09;&#xff0c;简称“世界杯”…

Vue中的数据代理与数据劫持

数据代理 数据代理字面上是通过一个对象代理对另一个对象属性的操作在vue中的数据代理&#xff0c;实际上是通过vm上的属性代理对_data中属性的操作 数据劫持 数据劫持也可称作数据代理&#xff0c;字面上是劫持到某个属性的变化&#xff0c;去做其他的操作在vue中的数据劫…

练习:查询学生新学期选课(python之str、dict、list试炼)

查询学生新学期选课(python之str、dict、list试炼)&#xff0c;数据用字典、列表存储。考验字符串的各种转换&#xff0c;字典、列表的读写。 (本文获得CSDN质量评分【88】)【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免…

【Git 教程系列第 26 篇】Mac 升级系统到 Ventura 后,Git 公钥报 Permission denied 错误问题的解决方案

这是【Git 教程系列第 26 篇】&#xff0c;如果觉得有用的话&#xff0c;欢迎关注专栏。 注&#xff1a; 如果你是因为升级系统到 Ventura 后遇到的这个问题&#xff0c;可以直接看第三步的解决方案&#xff0c;前两步是我自己的写作习惯&#xff0c;只是记录一下这个过程&…

Qt OpenGL 图形字体的纹理映射

这次教程中&#xff0c;我们将在第14课的基础上创建带有纹理的字体&#xff0c;它真的很简单。也许你想知道如何才能给字体赋予纹理贴图&#xff1f;我们可以使用自动纹理坐标生成器&#xff0c;它会自动为字体上的每一个多边形生成纹理坐标。 这次课中我们还将使用Wingdings字…

BNext

又搬来了大神器啊 来自德国HassoPlattner计算机系统工程研究院的NianhuiGuo和HaojinYang等研究者提出了BNext模型&#xff0c;成为第一个在ImageNet数据集上top1分类准确率突破80%的BNN。 两年前&#xff0c;依靠早期 BNN 工作 XNOR-Net 起家的 XNOR.AI 被苹果公司收购&#…

redis基础5——redis的频道订阅和模式频道、redis主从复制、哨兵集群

文章目录一、发布订阅1.1 发布订阅过程1.2 发布订阅类型1.2.1 频道的发布订阅1.2.1.1 订阅频道* 实现原理1.2.1.2 发送消息* 实现原理1.2.1.3 退订频道* 实现原理1.2.2 模式的发布订阅1.2.2.1 订阅模式频道* 实现原理1.2.2.2 查询订阅与发布系统状态1.2.2.3 发送消息* 实现原理…

【c++基础】第三章 宏观部分:面向对象之类的层次结构与相互关系

第三章 宏观部分&#xff1a;面向对象之类的层次结构与相互关系关系has_a关系use_a关系&#xff08;友元关系&#xff09;is_a关系&#xff08;继承关系&#xff09;单继承多继承菱形继承多态&#xff08;polymorphic&#xff09;虚函数多态底层机制&#xff1a;虚函数、虚函数…

spring导入第三方资源

一、第三方资源配置管理 说明&#xff1a;以管理DataSource连接池对象为例讲解第三方资源配置管理 1 管理DataSource连接池对象 问题导入 配置数据库连接参数时&#xff0c;注入驱动类名是用driverClassName还是driver&#xff1f; 1.1 管理Druid连接池【重点】 数据库准备…

Android挂载系统分区执行mount和remount

第一种&#xff0c;通过adb挂载&#xff0c;需要root权限&#xff1b; adb root //adb 获取root权限&#xff1b; adb remount /system //从新挂载system目录或者说分区 第二种&#xff1a;通过Android下的Linux命令挂载&#xff0c;需要root权限&#xff1b; adb shell //…

【第八章 索引,索引结构,B-Tree,B+Tree,Hash,索引分类,聚集索引二级索引,索引语法】

第八章 索引&#xff0c;索引结构&#xff0c;B-Tree&#xff0c;BTree&#xff0c;Hash&#xff0c;索引分类&#xff0c;聚集索引&二级索引&#xff0c;索引语法 1.索引&#xff1a; ①索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。 ②特…