git存储原理

四种数据类型

实际上Git基于数据类型的不同,把对象分为四种:数据对象、树对象、提交对象、标签对象。Git文件系统的设计思路与linux文件系统相似,即将文件的内容与文件的属性分开存储,文件内容以“装满字节的袋子”存储在文件系统中,文件名、所有者、权限等文件属性信息则另外开辟区域进行存储。在Git中,数据对象相当于文件内容,树对象相当于文件目录树,提交对象则是对文件系统的快照,标签对象则是对提交信息的引用。

下面我们分别对每种对象进行说明(建议大家操作的时候观察一下.git/objects目录的变化)

数据对象

数据对象是文件的内容,不包括文件名、权限等信息。Git会根据文件内容计算出一个hash值,以hash值作为文件索引存储在Git文件系统中。由于相同的文件内容的hash值是一样的,因此Git将同样内容的文件只会存储一次。git hash-object可以用来计算文件内容的hash值,并将生成的数据对象存储到Git文件系统中:

$ echo 'version 1' | git hash-object -w --stdin
83baae61804e65cc73a7201a7252750c76066a30
$ echo 'version 2' | git hash-object -w --stdin
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
$ echo 'new file' | git hash-object -w --stdin
fa49b077972391ad58037050f2a75f74e3671e92

上面示例中,-w表示将数据对象写入到Git文件系统中,如果不加这个选项,那么只计算文件的hash值而不写入;–stdin表示从标准输入中获取文件内容,当然也可以指定一个文件路径代替此选项。上面讲数据对象写入到Git文件系统中,那如何读取数据对象呢?git cat-file可以用来实现所有Git对象的读取。

$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30
version 1
$ git cat-file -t 83baae61804e65cc73a7201a7252750c76066a30
blob

上面示例中,-p表示查看Git对象的内容,-t表示查看Git对象的类型。

我们能够对Git文件系统中的数据对象进行读写。但是,我们需要记住每一个数据对象的hash值,才能访问到Git文件系统中的任意数据对象,这显然是不现实的。数据对象只是解决了文件内容存储的问题,而文件名的存储则需要通过树对象来解决。

树对象

树对象是文件目录树,记录了文件获取目录的名称、类型、模式信息。使用git update-index可以为数据对象指定名称和模式,然后使用git write-tree将树对象写入到Git文件系统中:

$ git update-index --add --cacheinfo 100644 83baae61804e65cc73a7201a7252750c76066a30 test.txt
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579

–add表示新增文件名,如果第一次添加某一文件名,必须使用此选项;–cacheinfo <mode> <object> <path>是要添加的数据对象的模式、hash值和路径,<path>意味着为数据对象不仅可以指定单纯的文件名,也可以使用路径。另外要注意的是,使用git update-index添加完文件后,一定要使用git write-tree写入到Git文件系统中,否则只会存在于index区域。此时的效果类似于执行了git add命令

树对象仍然可以使用git cat-file查看:

$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30  test.txt
$ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
tree

树对象解决了文件名的问题,而且,由于我们是分阶段提交树对象的,树对象可以看做是开发阶段源代码目录树的一次次快照,因此我们可以是用树对象作为源代码版本管理。但是,这里仍然有问题需要解决,即我们需要记住每个树对象的hash值,才能找到个阶段的源代码文件目录树。在源代码版本控制中,我们还需要知道谁提交了代码、什么时候提交的、提交的说明信息等,接下来的提交对象就是为了解决这个问题的。

提交对象

提交对象是用来保存提交的作者、时间、说明这些信息的,可以使用git commit-tree来将提交对象写入到Git文件系统中:

$ echo 'first commit' | git commit-tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
db1d6f137952f2b24e3c85724ebd7528587a067a

上面commit-tree除了要指定提交的树对象,也要提供提交说明,至于提交的作者和时间,则是根据环境变量自动生成,并不需要指定。这里需要提醒一点的是,读者在测试时,得到的提交对象hash值一般和这里不一样,这是因为提交的作者和时间是因人而异的。此时相当于执行了git commit

提交对象的查看,也是使用git cat-file:

$ git cat-file -p d555a9dfc304e74a9557a5d92dc0807c20765104
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author defwang &lt;wangdefu@100tal.com&gt; 1607259906 +0800
committer defwang &lt;wangdefu@100tal.com&gt; 1607259906 +0800first commit$ git cat-file -t bb4de00acf2b259e767d8321e0fa3c865dae780e
commit

上面是属于首次提交,那么接下来的提交还需要指定使用-p指定父提交对象,这样代码版本才能成为一条时间线:

$ git update-index --add --cacheinfo 100644 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test2.txt
$ git write-tree
e6cebf205657fb2046b5f38877bbfa8c3ae2d05c
$ echo 'second commit' | git commit-tree e6cebf205657fb2046b5f38877bbfa8c3ae2d05c -p d555a9dfc304e74a9557a5d92dc0807c20765104
bb4de00acf2b259e767d8321e0fa3c865dae780e

使用git cat-file查看一下新的提交对象,可以看到相比于第一次提交,多了parent部分:

$ git cat-file -p bb4de00acf2b259e767d8321e0fa3c865dae780e
tree e6cebf205657fb2046b5f38877bbfa8c3ae2d05c
parent d555a9dfc304e74a9557a5d92dc0807c20765104
author defwang &lt;wangdefu@100tal.com&gt; 1607260467 +0800
committer defwang &lt;wangdefu@100tal.com&gt; 1607260467 +0800second commit

使用git log可以查看整个提交历史:

$ git log --stat bb4de00acf2b259e767d8321e0fa3c865dae780e
commit bb4de00acf2b259e767d8321e0fa3c865dae780e
Author: defwang &lt;wangdefu@100tal.com&gt;
Date:   Sun Dec 6 21:14:27 2020 +0800second committest2.txt | 1 +1 file changed, 1 insertion(+)commit d555a9dfc304e74a9557a5d92dc0807c20765104
Author: defwang &lt;wangdefu@100tal.com&gt;
Date:   Sun Dec 6 21:05:06 2020 +0800first committest.txt | 1 +1 file changed, 1 insertion(+)

有时候我们为了方便记忆某一次提交,会对该提交打一个tag进行标记,这就产生了标签对象

标签对象

$ git tag -a v1.0.0 bb4de00acf2b259e767d8321e0fa3c865dae780e -m "test tag"

当执行上面命令之后,.git目录下的refs目录中就会多一个文件

refs/tags└── v1.0.0

文件内容为为40位的hash码, 同样我们使用git cat-file读取该hash值

$ git cat-file -p 4599faa3ffb8042b85fce6f80cad2633b4ee01ff
object bb4de00acf2b259e767d8321e0fa3c865dae780e
type commit
tag v1.0.0
tagger defwang &lt;wangdefu@100tal.com&gt; 1607262079 +0800test tag
git cat-file -t 4599faa3ffb8042b85fce6f80cad2633b4ee01ff
tag

可见该对象的类型为tag

至此,我们已经知道了git的四种数据类型,blob、tree、commit、tag
Git中的数据对象解决了数据存储的问题,树对象解决了文件名存储问题,提交对象解决了提交信息的存储问题,标签对象则是对提交对象进行更形象的命名,从Git设计中可以看出,Linus对一个源代码版本控制系统做了很好的抽象和解耦,每种对象解决的问题都很明确,相比于使用一种数据结构,无疑更灵活和更易维护。

 

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

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

相关文章

详解设计模式:中介者模式

中介者模式&#xff08;Mediator Pattern&#xff09;也被称为调停者模式&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 中介者模式 是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类&#xff0c;该类通常处理不同类之间的通信&#xff0c;并支…

rebase参数以及注意事项

可以根据需要将pick参数&#xff0c;改变为下面代表不同作用的参数&#xff1b;这样就可以对节点C和D进行不同的操作了。比如&#xff1a; pick&#xff1a;默认参数&#xff0c;表示不对提交节点进行任何操作&#xff0c;直接应用原提交节点。不创建新提交&#xff1b; rewor…

RPC 服务 与 HTTP 服务的区别

1、什么是RPC RPC&#xff08;Remote Procedure Call&#xff09;—远程过程调用&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在&#xff0c;如TCP或UDP&#xff0c;为通信程序之间携带信…

Docker 网络命名空间

Docker 用户可以通过与 CNM 的 Object 以及 API 的交互来管理对应容器的网络&#xff0c;下面是一个典型的容器网络生命周期&#xff1a; 1、Driver要向NetworkController注册。内置的Driver在Libnetwork内注册&#xff0c;远程的Driver则通过Plugin mechanism注册。每一个Driv…

缓存雪崩、击穿、穿透解决方案

用户的数据一般都是存储于数据库&#xff0c;数据库的数据是落在磁盘上的&#xff0c;磁盘的读写速度可以说是计算机里最慢的硬件了。 当用户的请求&#xff0c;都访问数据库的话&#xff0c;请求数量一上来&#xff0c;数据库很容易就奔溃的了&#xff0c;所以为了避免用户直…

Ansible中的playbook详解

首先简单说明一下playbook&#xff0c;playbook是什么呢&#xff1f; 根本上说playbook和shell脚本没有任何的区别&#xff0c;playbook就像shell一样&#xff0c;也是把一堆的命令组合起来&#xff0c;然后加入对应条件判断等等&#xff0c;在shell脚本中是一条一条的命令&am…

【Docker】容器镜像有哪些特性

首先解释一下什么是Docker镜像&#xff1f; Docker镜像它其实是一个模板&#xff0c;拥有这个模板我们才能创建我们的Docker容器&#xff0c;镜像里含有启动 docker 容器所需的文件系统结构及其内容&#xff0c;因此是启动一个 docker 容器的基础。docker 镜像的文件内容以及一…

nginx中的location指令

1、location 介绍 location是Nginx中的块级指令(block directive)&#xff0c;location指令的功能是用来匹配不同的url请求&#xff0c;进而对请求做不同的处理和响应&#xff0c;这其中较难理解的是多个location的匹配顺序&#xff0c;本文会作为重点来解释和说明。 开始之前…

容器底层实现技术Namespace/Cgroup

Docker容器实现原理 Docker容器在实现上是通过namespace技术来进行进程隔离&#xff0c;通过cgroup技术实现容器进程可用资源的限制&#xff0c;当docker启动一个容器时&#xff0c;实际是创建了多了namespace参数的进程。 Namespace Namespace&#xff1a;命名空间 作用&#…

身体原因 断更一周

由于众所周知的原因&#xff0c;博主最近具有发热、全身乏力、酸痛、干咳等症状&#xff0c;已严重影响日常的工作学习和博客编写&#xff0c;所以断更我将一周&#xff0c;由下周三&#xff08;即2022年12月21日&#xff09;恢复更新 更多往期内容可以参考&#xff1a;全网最…

异方差与多重共线性对回归问题的影响

异方差的检验 1.异方差的画图观察 2.异方差的假设检验&#xff0c;假设检验有两种&#xff0c;一般用怀特检验使用方法在ppt中&#xff0c;课程中也有实验&#xff0c;是一段代码。 异方差的解决办法 多重共线性 多重共线性可能带来的影响&#xff1a; 多重共线性的检验 多重…

如何修改Docker的镜像源

改或新增/etc/docker/daemon.json 文件 vi/etc/docker/daemon.json 添加需要修改的国内镜像源镜像源 { "registry-mirrors":["http://hub-mirror.c.163.com"] } 重启Docker服务 Systemctl restart docker.service 方法二 修改或新增 /etc/sysconfig…

nginx 的 rewrite 模块

ngxhttprewrite_module 模块用来使用正则表达式&#xff08;PCRE&#xff09;改变请求的 URI&#xff0c;返回重定向&#xff0c;并有条件地选择配置。 指令执行顺序 首先顺序执行 server 块中的 rewrite 模块指令&#xff0c;得到 rewrite 后的请求 URI 然后循环执行如下指令…

所有的Python库

库名称简介 Chardet字符编码探测器&#xff0c;可以自动检测文本、网页、xml的编码。 colorama主要用来给文本添加各种颜色&#xff0c;并且非常简单易用。 Prettytable主要用于在终端或浏览器端构建格式化的输出。 difflib&#xff0c;[Python]标准库&#xff0c;计算文本…

Oracle行转列语法总结大全

一、decode语法 SELECT deptno, nvl(SUM(decode(job, MANAGER, sal)), 0) s_MANAGER, nvl(SUM(decode(job, ANALYST, sal)), 0) s_ANALYST, nvl(SUM(decode(job, CLERK, sal)), 0) s_CLERK, nvl(SUM(decode(job, PRESIDENT, sal)), 0) s_PRESIDENT, …

Shell 各种符号 之 含义

#!&#xff1a;符号能够被内核识别成是一个脚本的开始&#xff0c;这一行必须位于脚本的首行 $0&#xff1a;当前脚本的名字 $#&#xff1a;输入<调用>参数(脚本或函数的位置参数) 的个数&#xff0c;如 NumArg$#&#xff1b;echo"\$#: $#;\$NumArg: $NumArg"…

Nginx的11个执行流程

1 Nginx简介 Web服务器市场份额 Nginx [engine x] 最初由 Lgor Sysoev 编写。根据 Netcraft 的数据&#xff0c;到2020年9月&#xff0c;Nginx 服务或代理了25.76&#xff05;站点&#xff0c;市场份额占到了约34.03&#xff05;。 Nginx 被广泛用作&#xff1a; HTTP服务器…

Nginx的执行阶段详解

在了解nginx的执行阶段前&#xff0c;先看一个例子 对echo不熟悉的&#xff0c;可以先看文章Nginx调试必备了解下echo扩展 回到上面这个例子&#xff0c;在server块中配置这样的location&#xff0c;你觉得输出是什么样子&#xff1f; 按照正常的逻辑&#xff0c;输出应该是32 …

Docker挂了,数据如何找回

docker在实际使用中&#xff0c;让运维人员诟病的&#xff0c;除了安全问题外&#xff0c;大概就是数据的问题了 很多人在初用docker的时候&#xff0c;很多时候都忘记或不知道docker中需要保留的数据需要挂载到宿主机文件夹到容器内部对应目录&#xff08;当然除了挂载宿主机目…

TCP总结

TCP这些东西&#xff0c;基本每个程序猿都或多或少是掌握的了。虽然感觉在实际开发中没有什么用武之处&#xff0c;但&#xff0c;面试他要问啊 而最近大家伙过完年&#xff0c;也都在准备春招&#xff0c;我也一样。阅读了一些okHttp源码之后&#xff0c;又屁颠屁颠地跑回来重…