1.前言

git包含四种对象文件:

  • blob
  • tree
  • commit
  • tag(目前没用到,暂时忽略)

2. git对象的关系

 
图 git三种对象关系
 

粗略一看,可以大致感觉出blob类似于文件,而tree类似于文件夹,而commit则是囊括这一大堆东西的一个对象。

3.SHA-1算法

SHA-1算法具体怎么计算,可以自行google。这里只说一下该算法在git数据存储中的应用。我们可以用git提供的命令来计算一个文件的SHA-1值:

echo 'test content' | git hash-object --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4

输入字符串 "test content",git会通过SHA-1算法将其中的内容计算出一个40个字符的HASH值。

同样地,如果我们在工作区新增一个文件,然后通过 git add 加入到暂存区,那么git同样地会根据这个文件通过SHA-1算法来计算出属于该文件的一个HASH值。

这个值是唯一的!如果一个文件经过修改之后,再次计算得到的HASH值会不会和原来的一样?答案是肯定不会的,所以这个HASH值就可以充当一个标识符的作用。

4.git如何存储对象

git add后发生什么?

对于blob对象,仔细观察上一副图可以发现,blob对象的头顶都有着5个字符,"5b1b3","911e7","cba0a"。其实这一段字符串就是所属文件的HASH值的一部分。

那么它为什么会出现在blob的头顶呢?其实当把一个新的文件放入到暂存区之后,git就在自己的目录下 .git/object/ 新建了一个文件对象,来保存新加入的文件,

与此同时通过SHA-1算法来计算得到一个所属该对象的"标识",而这个对象,就是blob对象。(感觉说的有点拗口)。大致过程如下图:

 
图 git add后git对象情况

git commit后发生什么?

 
图 git commit后git对象情况

没错,又多出了两个hash值,即代表了两个对象。同时考虑到上边那个关系图可以大致猜测到,提交之后,又生成了两个对象,一个tree对象,一个commit对象。

不过如果继续带着好奇心深入下去,尝试着去打开其中的一个文件,会发现里边是一堆16进制的数字,即使用Winhex打开,也是乱码。这是因为git对原来文本中的数据进行了重新压缩编码,这样既可以保存原来的文本内容,又减少了对空间的占用。

5. git指针

提到指针,那就肯定要稍微提一下C、C++中的指针了。这种指针的作用很简单,就是存储一个变量的地址,然后根据这个地址来找到该对象,进而对其进行操作。

那么,git中的指针也是这样的吗?其实,也差不多。只不过这里存储的并不是变量的在内存上的地址,而是另外一种形式的"地址",这就是HASH值。

没错,就是上边计算出来的那个HASH值,commit对象的HASH值。

 
图 commit对象的HASH值

在上副图中,我对Doge.txt文件又进行了修改,然后又放入到暂存区中,接着进行commit提交操作,然后输入命令 git log 来查看所有提交的日志记录,我们可以看到有一排黄色的字符串,写着 commit cbfa20cb4fc205477237d3ffc88909f7cb49bd6f,这就是我们次此提交之后生成的commit对象的HASH值。那么,指针在哪里呢?不急,接下来看下边这幅图:

 
图 git指针

这个文件是master文件,在 .git/refs/ 目录下。为什么要看这个文件呢?我们在用git的时候,经常会看到master这个单词,它是git中默认的一个分支,简单点说这个master文件就是一个指针,这个指针记录着一个commit提交对象的HASH值,通过这个HASH值我们就可以找到本次提交的tree对象、blob对象,这样也就找到了我们提交的文本信息了。

6. git版本回退

回顾一下我们刚才走过的路,我们知道一次提交就对应着个commit对象,一个commit对象还带着一个唯一标识的HASH值,那么按照这样的逻辑来推理的话,两次提交就有会两个commit对象,两个不同的HASH值。如果要版本回退的话,是不是我们只要指定一下回退到第几个版本,然后获得相应的commit对象就可以做到了?先来简单地试验一下吧:

 
图  现在版本
 
图 两次提交后的commit

图中有两行数据,同时在本地版本库中也有两个版本

 
图 版本回退
 
图 回退之后的文本

上边是一个简单的版本回退示意图,通过输入命令 git reset 版本id 来回退到指定的版本。其实一个最简单的版本回退就是如此。

其实在内部,就是将带有HASH值的HEAD指针从最新的一个提交对象上转移到上一个提交对象上。

对于版本回退,还有许多其他的用法,包括reset的一些参数使用,checkout、revert命令的使用。有关它们的具体用法请戳这个传送门:
代码回滚:Reset、Checkout、Revert的选择

7.总结

这篇文章重点不是介绍git的命令用法,而是对其内部原理的一个简单分析。我写的比较白话,而且一直感觉有些地方不够完善,详略不太得当,但也没考虑好怎么去修改、完善。希望自己在以后的不断回看中,能够逐渐完善。

参考文章

Git 工作区、暂存区和版本库
使用原理视角看 Git
《Pro Git》的笔记-git内部原理
Git 用起来 の 基本原理

https://www.jianshu.com/p/9291dd3a99b3 深入git数据存储原理

作者:雅俗共赏M
链接:https://www.jianshu.com/p/9291dd3a99b3
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

git知识总结-1.git基础之数据存储的更多相关文章

  1. Git知识总览(二) git常用命令概览

    上篇博客我们从 git clone 和 git status 两个命令开始,引出了一系列的git操作命令, 请参见:<Git知识总览(一) 从 git clone 和 git status 谈起 ...

  2. Git知识总览(四) git分支管理之rebase 以及 cherry-pick相关操作

    上篇博客聊了<Git知识总览(三) 分支的创建.删除.切换.合并以及冲突解决>,本篇博客我们主要来看一下 rebase 变基相关的操作.rebase 操作和 merge 操作最终都可以达到 ...

  3. Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase

    上篇博客聊了<git分支管理之rebase 以及 cherry-pick相关操作>本篇博客我们就以Learning Git中的关卡进行展开.下方列举了LearningGit中的 merge ...

  4. Git知识总览(六) Git分支中的远程操作实践

    前几篇博客陆陆续续的讲了好多关于Git操作的内容,本篇博客仍然也不例外,不过本篇博客的主题是关于git的远程操作的.依照之前博客的风格,我们依然依托于LearningGitBranch中的相关内容来探 ...

  5. git知识总结-4.git服务器搭建及迁移git仓库

    1. 前言 因为手里有一份代码之前是直接从其它git服务器上克隆下来的,现在想自己搭建一个git服务器把这份代码管起来. 2. 搭建git服务器 1.安装git: $ sudo apt-get ins ...

  6. git知识总结-2.git基本操作之原理说明

    0.前言 本文主要对git常用命令的工作原理做一个详细的说明,常用命令主要包括: 1.git add git add相关命令很简单,主要实现将工作区修改的内容提交到暂存区,交由git管理. 2. gi ...

  7. git知识总结-2.git基本操作之操作汇总

    0.前言 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令. 上图分别为: Workspace:工作区 Index / Stage:暂存区 Reposito ...

  8. <Android基础> (六) 数据存储 Part 1 文件存储方式

    第六章 数据存储 6.1 持久化技术 持久化技术指将内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失. 主要有三种方式用于简单地实现数据持久化功能:文件存储.S ...

  9. node.js基础:数据存储

    无服务器的数据存储 内存存储 var http = require('http'); var count = 0; //服务器访问次数存储在内存中 http.createServer(function ...

随机推荐

  1. OpenStack端口(15)

    一.OpenStack组件使用的默认端口号 openstack openstack service default ports port type keystone Identity service ...

  2. CSS3 border-radius 圆角

    圆角border-radius,其css如下 IE9+支持(就是ie6,ie7,ie8都不支持),默认值是0,不继承,可以像下面那样设置4个角的值,也可以单独设置,如 border-top-left- ...

  3. PowerDesigner 批量添加字段

    Option Explicit Dim mdl ' the current model Set mdl = ActiveModel Dim Tab 'running table Dim col_1 D ...

  4. MCMC算法解析

    MCMC算法的核心思想是我们已知一个概率密度函数,需要从这个概率分布中采样,来分析这个分布的一些统计特性,然而这个这个函数非常之复杂,怎么去采样?这时,就可以借助MCMC的思想. 它与变分自编码不同在 ...

  5. JSP元素介绍

    1.HTML注释 <!--这个HTML注释--> 2.JSP注释 <% --这是JSP注释-- %> 3.声明 用于在页面中定义变量或方法 <% ! String use ...

  6. 轻松理解 Spark 的 aggregate 方法

    2019-04-20 关键字: Spark 的 agrregate 作用.Scala 的 aggregate 是什么 Spark 编程中的 aggregate 方法还是比较常用的.本篇文章站在初学者的 ...

  7. 【简】题解 AWSL090429 【数塔问题】

    因为每次只ban一个点 而且不是永久性的 预处理出每个点从上往下和从下往上的最大值 每次询问直接暴力 被ban掉点那行去掉那点的最大值 也可以直接预处理出每行的最大值和次大值 还有种做法貌似可以过 预 ...

  8. The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...

  9. 关于使用stanfordcorenlp一直运行不报错的解决方法

    一.问题描述: 最近在使用stanfordcorenlp时,遇到了我在运行时代码不报错但同时也没有结果的问题,等了很久也没有出结果.其实是很简单的一个步骤,但却花了好几天的时间都没有成功!网上更多的是 ...

  10. 超越村后端开发(5:远程同步本地与服务器端的MySQL数据库)

    1.同步MySQL数据库 服务器选用的华为云,安装了Ubuntu18.04,华为云默认是以root用户登录的. 1.使用Xshell6连接华为云 ls 2.Ubuntu18.04安装MySQL5.7 ...