浅谈GIT之底层对象理解

一、基本概述

首先定下一个基调就是Git并不是比SVN任何方面都好。SVN在某些功能或方面或者某些场景下也优于Git。

只是这篇文章讨论涉及到的点要与SVN相比,然后突出Git的某些方面的优越性而已。

对于Git而言,它本身是一个内容寻址文件系统,会将需要存储的东西按元数据meta data方式存储在一个KV数据库里面,

类似HashMap的这样的键值对结构,然后会按照内容生成相应的唯一hashcode作为内容的key,

而对于SVN而言,则是按照文件方式存储。

所以,看出一个特点就是如果需要的功能中涉及到文本的对比的话,对于Git而言是毫不费力的,因为只要对比hashcode

是否一个就知道两个文本是否相同了。

在这里介绍Git底层相关的三类对象:Git存储对象,Git树对象和Git的提交对象

二、底层介绍

2.1、Git的存储对象

Git将文件内容保存到内置的kv数据库的时候会根据内容产生并返回一个hash键

下面在Git Bash中模拟Git保存内容以及回滚的内部实现

 1 [email protected] MINGW64 /e/git_study/jay4 (master)
 2 $ find .git/objects/ -type f
 3
 4 [email protected] MINGW64 /e/git_study/jay4 (master)
 5 $ echo ‘hello git1‘ > git.txt; git hash-object -w git.txt;
 6 warning: LF will be replaced by CRLF in git.txt.
 7 The file will have its original line endings in your working directory.
 8 665c1e58d062e749beac9d853c94cb435b711498
 9
10 [email protected] MINGW64 /e/git_study/jay4 (master)
11 $ echo ‘hello git2‘ > git.txt; git hash-object -w git.txt;
12 warning: LF will be replaced by CRLF in git.txt.
13 The file will have its original line endings in your working directory.
14 a8b60e8197d9f9025c13aaca6971a0738309d858
15
16 [email protected] MINGW64 /e/git_study/jay4 (master)
17 $ find .git/objects/ -type f
18 .git/objects/66/5c1e58d062e749beac9d853c94cb435b711498
19 .git/objects/a8/b60e8197d9f9025c13aaca6971a0738309d858
20
21 [email protected] MINGW64 /e/git_study/jay4 (master)
22 $ git cat-file -p ^C
23
24 [email protected] MINGW64 /e/git_study/jay4 (master)
25 $ git cat-file -p a8b60e8197d9f9
26 hello git2
27
28 [email protected] MINGW64 /e/git_study/jay4 (master)
29 $ git cat-file -p 665c1e58d062e > git.txt

解释上述内容:

第二行,$ find .git/objects/ -type f 这个命令是查找在.git/objects/这个目录下文件,结果是无

第五行,$ echo ‘hello git1‘ > git.txt; git hash-object -w git.txt;  这个命令是输入文本内容到

git.txt文件中,然后通过git hash-object -w保存起来

并返回一个hashcode:665c1e58d062e749beac9d853c94cb435b711498

通过两次保存的操作,再调用一次$ find .git/objects/ -type f 可以看到再.git/objects/

有两个目录的生成,可以看出目录名字数字的拼接就是生成的hashcode

.git/objects/66/5c1e58d062e749beac9d853c94cb435b711498

.git/objects/a8/b60e8197d9f9025c13aaca6971a0738309d858

第二十五行,$ git cat-file -p a8b60e8197d9f9,通过这个命令可以根据hashcode返回

保存的文本内容 “hello git2”

也正因此,$ git cat-file -p 665c1e58d062e > git.txt ,根据以前的hashcode找回旧的内容输入

到对应文件,完成回滚操作

那么在实际操作Git的过程中,保存在KV库就是对应于git add命令的执行,也就是我们执行

git add xxx就相当于执行 git hash-object -w xxx的操作

记住一个点就是生成Git的存储对象是根据文件的内容而生成的,

也就是在存储对象中并没有保存Git文件的名字,也就是还不清楚文件内容与文件名称的映射关系,

所以假如需要进行回滚操作并不清楚该文件能够回滚到什么文件内容了。

而树对象则解决了这个问题。

2.2、Git的树对象

因为保存到Git的时候肯定文件中有相应的文件与文件夹的结构

Git的树对象其实是为了组织或者映射保存时的结构,类Unix的文件系统层次。可以从中看到对保存的内容的映射关系

如上图所属,一个树对象(tree object) 可能会包含多个文件(也就是 blob object,内部以二进制文件进行处理保存)

以及多个树对象(tree object,可以理解为文件夹)

由于每一个分支都有一个指向一个树对象,

因此可以通过以下命令根据key查看master分支中树对象的内容  master^{tree}指对应树对象的key

git cat-file -p master^{tree}

通过以下命令解说一下

 1 [email protected] MINGW64 /e/git_study/jay (master)
 2 $ mkdir -p src/main/
 3
 4 [email protected] MINGW64 /e/git_study/jay (master)
 5 $ echo ‘hi git‘ > ./src/main/demo.java
 6
 7 [email protected] MINGW64 /e/git_study/jay (master)
 8 $ git add -A
 9 warning: LF will be replaced by CRLF in git.txt.
10 The file will have its original line endings in your working directory.
11 warning: LF will be replaced by CRLF in src/main/demo.java.
12 The file will have its original line endings in your working directory.
13
14 [email protected] MINGW64 /e/git_study/jay (master)
15 $ git commit -am ‘tree object‘;
16 [master (root-commit) f3484a7] tree object
17  2 files changed, 3 insertions(+)
18  create mode 100644 git.txt
19  create mode 100644 src/main/demo.java
20
21 [email protected] MINGW64 /e/git_study/jay (master)
22 $ git log
23 commit f3484a7829d2b32f5c6b4579575cacdf76abe588 (HEAD -> master)
24 Author: hjj <[email protected]>
25 Date:   Mon Feb 3 22:17:12 2020 +0800
26
27     tree object
28
29 [email protected] MINGW64 /e/git_study/jay (master)
30 $ git cat-file -p f3484a7829d2b32f5c6b4579575cacdf76abe588
31 tree a6f44ae816a4c755d2a568cb9055a7eb860a1776
32 author hjj <[email protected]> 1580739432 +0800
33 committer hjj <[email protected]> 1580739432 +0800
34
35 tree object
36
37 [email protected] MINGW64 /e/git_study/jay (master)
38 $ git cat-file -p a6f44ae816a4c755d2a568cb9055a7eb860a1776
39 100644 blob 5b317be9a8665279f1d3b01e009211380442e337    git.txt
40 040000 tree 9451f6d961aa89ae596202edff4ee0a57e528e15    src

在上述中我先创建文件夹src,main,然后创建一个文件demo.java

然后再对文件进行git add和git commit操作

接着再通过git log查看这次的提交日志,从中得到提交信息

1 commit f3484a7829d2b32f5c6b4579575cacdf76abe588 (HEAD -> master)
2 Author: hjj <[email protected]>
3 Date:   Mon Feb 3 22:17:12 2020 +0800

主要是获取提交对象(commit object)的key

然后在30行,通过命令 $ git cat-file -p f3484a7829d2b32f5c6b4579575cacdf76abe588、

得到以下信息,从中可以得到这次提交中所指向的树对象的key

1 tree a6f44ae816a4c755d2a568cb9055a7eb860a1776
2 author hjj <[email protected]> 1580739432 +0800
3 committer hjj <[email protected]> 1580739432 +0800

然后在38行通过命令 $ git cat-file -p a6f44ae816a4c755d2a568cb9055a7eb860a1776

可以查看到树对象包含的信息:

类型编码  类型  key  对象的名称

100644   blob   5b317be9a8665279f1d3b01e009211380442e337   git.txt

040000   tree   9451f6d961aa89ae596202edff4ee0a57e528e15   src

因此在树对象中映射相应的文件结构以及文件名与存储对象的key的映射

再往下进行解读,如下图所示:

每个树对象(文件夹)和每个存储对象(文件)与对应的hash key以及相应的文件结构

2.3、Git的提交对象

在讲述Git的树对象中,还涉及到一个提交对象(commit object)。其实在Git中每次提交都会生成一个提交对象,该对象内容存储着

一个顶级树对象的key,上次提交的顶级树对象key,提交人的名称\邮箱\时间戳,以及提交评论

$ git cat-file -p f38854cec27f8614fd7bea3e8fa256724302d7c8

tree 84e18d1503ab30cf5443af78a08d95ee56fb34ac          ----- 当前顶级树对象的key
parent f3484a7829d2b32f5c6b4579575cacdf76abe588     ----- 上次提交顶级树对象的key
author hjj <[email protected]> 1580742512 +0800                   -----  提交人的名称\邮箱\时间戳
committer hjj <[email protected]> 1580742512 +0800             ----- 提交人的名称\邮箱\时间戳

commit object                                           ----- 提交评论


以上看出最关键的是提交对象,通过每一次提交就会生成一个提交对象,然后将

关联的当前版本中的所有文件的blob object的key通过树对象组织和关联起来形成这一次的版本

也就是每次提交只是保存对应文件的key的组织集合,所以成本很小。

同时每次做版本回滚只要比对key是否相同,然后如果不同,就将旧版本key对应的内容找出来切换,就完成了,

所以速度很快。

2.4、分支的创建

在git中创建分支,可以利用 git branch <branch name> 基于当前分支创建,或者可以通过指定的分支名/commit id/远程分支名/tag名创建。

其实创建一个分支相当于在.git\refs\heads下创建一个引用的文件

 1 [email protected] MINGW64 /e/git_study/jay (master)
 2 $ find .git/refs/heads/ -type f
 3 .git/refs/heads/master
 4
 5 [email protected] MINGW64 /e/git_study/jay (master)
 6 $ git branch dev
 7
 8 [email protected] MINGW64 /e/git_study/jay (master)
 9 $ find .git/refs/heads/ -type f
10 .git/refs/heads/dev
11 .git/refs/heads/master
12
13 [email protected] MINGW64 /e/git_study/jay (master)
14 $ git log
15 commit f38854cec27f8614fd7bea3e8fa256724302d7c8 (HEAD -> master, dev)
16 Author: hjj <[email protected]>
17 Date:   Mon Feb 3 23:08:32 2020 +0800
18
19     commit object
20
21 commit f3484a7829d2b32f5c6b4579575cacdf76abe588
22 Author: hjj <[email protected]>
23 Date:   Mon Feb 3 22:17:12 2020 +0800
24
25     tree object

以上操作就基于master分支创建一个dev分支,并看到在.git/refs/heads目录下创建了一个dev文件,文件内容是

可以看出dev中保存的就是master分支所指向最新那次提交的提交对象的key。

所以至少看出一点就是在Git中创建分支几乎是没什么成本,就是创建一个文件保存引用

本文作者:hjjay
原文出处:https://www.cnblogs.com/jayhou/p/12250859.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

原文地址:https://www.cnblogs.com/jayhou/p/12250859.html

时间: 2024-10-07 22:02:57

浅谈GIT之底层对象理解的相关文章

浅谈Java中的对象和引用

浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是"对象和对象引用",很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起了解一下对象和对象引用之间的区别和联系. 1.何谓对象? 在Java中有一句比较流行的话,叫做"万物皆对象",这是Java语言设计之初的理念之一.要理解什么是对象,需要跟类一起结合起来理解.下面这段话引自<Java编程思想>中的一段原话: "按照通

浅谈Java中的对象和对象引用

浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起了解一下对象和对象引用之间的区别和联系. 1.何谓对象? 在Java中有一句比较流行的话,叫做“万物皆对象”,这是Java语言设计之初的理念之一.要理解什么是对象,需要跟类一起结合起来理解.下面这段话引自<Java编程思想>中的一段原话: “按照通俗的说法,每个对象都是某个类(class)的一个实

【转载】李航博士的《浅谈我对机器学习的理解》 机器学习与自然语言处理

李航博士的<浅谈我对机器学习的理解> 机器学习与自然语言处理 [日期:2015-01-14] 来源:新浪长微博  作者: 李航 [字体:大 中 小] 算算时间,从开始到现在,做机器学习算法也将近八个月了.虽然还没有达到融会贯通的地步,但至少在熟悉了算法的流程后,我在算法的选择和创造能力上有了不小的提升.实话说,机器学习很难,非常难,要做到完全了解算法的流程.特点.实现方法,并在正确的数据面前选择正确的方法再进行优化得到最优效果,我觉得没有个八年十年的刻苦钻研是不可能的事情.其实整个人工智能范畴

浅谈元类(个人理解)

浅谈元类(个人理解) 我们知道在python中一切皆对象(object),那么所以有的对象都成了object的子类,那么object类又是由谁创建的呢? 实际上,能够创建类的类,叫元类.还有一个概念就是:元类创建了object类,同时又是object类的子类(这是什么鬼?我们就不去考虑这个逻辑了,已经完美解决了先有鸡还是先有蛋的问题了). 元类实际还是所有类的创建者,即使所有类(包括元类自己)都是object的子类,他们的关系如下: Interesting...... 原文地址:https://

浅谈GIT

浅谈GIT: 牛老师提出的git,于我而言,是一个陌生和新鲜的词汇,在此之前我从未听过git,按照老师的要求,我去搜索了关于git的介绍,有些看懂了,但大部分还是不懂得,在介绍中我了解git其实之前使用的人并不多,因为它的资料比较少,学习它所耗费的时间也比较长,而且它并不符合我们的惯性思维,但这些缺点在近几年不断的研究和更新中也慢慢的被克服,使用它并知道它的人也越来越多,人们发现它越来越多的优点,比如git的速度很快,这对一些大项目来说是非常重要的,它还支持离线工作,而且git的公共服务器压力和

【浅谈git常用命令】

前言 本篇是继<浅谈git如何使用>之后介绍常用的git指令操作,如果还有了解过git的朋友们,建议先看看这篇博客,这篇博客主要是介绍如何动手安装git的环境.如何将本机绑定github账号.如何在github上创建仓库及如何将本地仓库与远程仓库关联等.<浅谈git如何使用>:http://blog.csdn.net/u010989191/article/details/51225071. Git指令介绍 本次演示仍是继上次创建的仓库first,一切在此基础上演示. 1 .创建版本

再谈git和github-深入理解

git中的 objects 和 refs 是什么? 如何理解 HEAD? 如何理解git github的工作过程? 参考: https://www.zhihu.com/question/20070065 为什么git能够回滚到历史记录呢? 是因为每一次提交 commit, 就相当于 做了依次 项目/工程的 备份点一样, 每次 提交时 都会生成一个 唯一的 commit id, 一个 hash值 所以如同windows 的系统备份点一样, 可以保存多个备份点, 然后你可以选择 随时恢复到 / 回滚

10 浅谈 装饰器模式的理解与使用

在不改变现有类结构的情况下,为这个类添加一个新的功能,这就是装饰器模式 所属与结构型模式, 这种模式的特点是:需要创建一个装饰类来包装原有的类,并且提供额外的功能. 为了解决:平时使用继承的方式,会带入许多静态的方法,导致子类过度饱和,膨胀. 举例子:悟空拥有七十二变,不管它怎么变化,他的本质还是一只猴子,但是他又有变化后的一些本领(功能) 实现:装饰类包含原有类的实例对象,即可实现装饰器模式 开始: 定义一个形状的接口 //画图接口 public interface Shape { void

浅谈对差分隐私的理解

在听完第五组的报告之后,浅谈一下对差分隐私的认识,主要针对差分隐私的思想做一个大致的梳理. 为什么会产生差分隐私? 由于有些“聪明”的用户为了知道某些信息,可以通过两次查询结果的差异进行对比,从而在两次数据的对比中找到有用的信息.正如在杨顼组的报告中提到的查询二等兵约瑟夫阿伦是否阵亡的信息,可以通过查询D5和D6两次数据结果,将两次数据结果进行对比就可以知道约瑟夫阿伦是否阵亡的消息. 差分隐私的主要思想: 差分隐私是基于噪音的安全计算方法,它的思想是:对计算过程用噪音干扰,让原始数据淹没在噪音中