【Git常用】之深入理解Git存储文档的方式

0 快照

相信了解Git的朋友,在阅读Git相关资料的时候,一定会读到:Git记录文件的快照(snapshot),而不是差异的部分。

到底什么是快照

《Git Pro》中英文原文如下:

Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.
每当读者在Git中提交或保存你的工程的状态的时候,总的来说,Git为那一刻,所有你的文件的状态的做了一份“快照”并存储了一个引用到那份“快照”。

读到这里,请读者先在脑海中有一个模糊的观念:快照就是一段程序的输出结果;在提交或保存文件状态时,Git输入当前文件的状态,输出一个快照

引用《Git Pro》中的图片,我们先来宏观体验一下。

图1 Git存储每次文件更新时的快照

比如我当前处于Version 1时刻,此时修改了文件A、C,修改后的文件分别记为A1、C1,我们进入到了Version 2时刻。

对于Git来说,只要两个文件的SHA-1不同,则这两个文件就是两个文件。因此,Git发现A1与A的SHA-1不同,B的相同,C的不同。

当我们提交或保存工作工程状态的时候,Git便把此时A、B、C三个文件复制到.git的隐藏文件夹中的某个目录,以Git的方式编码存储起来,并记录好引用到A1,B,C1的相关信息等,以便日后找到。

此时Git的版本库中,A有修改,因此有A和A1两个文件;B并没有被修改,因此B存储的只有一份;C有修改,因此有C和C1两个文件;共5个工程文件。

上述,便是Git记录文件快照的过程;上述提到的相关信息便是广义上的快照

1、实验

1.1 实验过程

让我们做个实验体验一下。

实验环境:Windows 10,Git版本2.18.0

图2 实验环境

我们在目录下面新建一个test.txt的文件,里面输入内容“This is a test.”。

图3 第一个文件

然后初始化目录为git仓库。

图4 初始化Git仓库

我们发现,出现了一个隐藏文件夹.git。我们点开来,发现如下结构:

图5 .git文件夹下的目录结构

这里我们主要关心objects文件夹,点开来看,现在有两个文件夹,info和pack。

图6 objects文件夹的内容

我们再开一个窗口,然后把刚刚建的test.txt提交到暂存区,看看objects下面发生了什么。

图7 执行git的add命令

objects文件夹下面多了一个文件夹叫27,打开来,里面有以一串以字母和数字为名字的文件。

图8 多了一个文件

紧接着,我们提交test.txt,执行

$ git commit --all -m "first commit"

图9 提交

我们发现,又多了两个文件夹b7和ba。打开来看,依旧是有一个以一串字母和数字为名字的文件。

至此,一个文件,被git成功拍了一张快照,记录在册。

1.2 实验解析

objects下面的文件夹的名字有何意义?为什么一次提交会新建三个文件夹?

我参考《Git Pro》中的讲解,为大家解析。

Git每次提交,会生成三类东西:

  1. 一个提交,commit
  2. 一个树,tree
  3. 一些文件的快照,blob

他们三者相关关系如下图

在这里插入图片描述

上图只是示意图,只列出了Git存储文档时关键的内容。

关于blob

我们发现,当我们执行$ git add <file>…时,生成了一个27文件夹,里面只有一个文件,这便是Git进行快照的方式——Git使用blob类型的数据结构存储这些快照,并计算SHA-1值,SHA-1值的前两个字符作为文件夹名称,后续作为文件名称。

关于tree

当我们提交这次修改的时候,Git生成了一个tree数据结构,用来管理本次提交涉及到的所有文件。因为实验只涉及到一个文件,因此tree中的内容只有一个。Git把tree保存成文件,保存成文件的方法和保存文件快照的方法一样——生成SHA-1值,前两个字符作为文件夹名称,后续作为文件名称,便生成了本次实验的b7文件夹。

关于commit

然后才是Git针对本次的提交记录,一个commit数据结构。commit记录了一些本次提交的重要内容,如提交者、作者、附注等,最重要的就是指向tree的指针tree指向父提交的指针parent。指向tree的指针,保证本次提交的所有快照可以被找到;指向父提交的指针,保证了分支功能。同样的,将这些内容保存成文件,生成SHA-1值,前两个字符作为文件夹名称,后续作为文件名称,便生成了ba文件夹。

可以利用$ git log 查看

在这里插入图片描述

log中显示的SHA-1正好是文件夹ba与里面文件e9176e…连接起来的内容。

当我们不关注tree和blob,只关注提交时,将每次的提交,以结点网络图的形式连接起来,便变成下面的样子。

在这里插入图片描述

在进一步,抽象成结点。

在这里插入图片描述

这看起来,就像一条分支了。

1.3 结论

至此,我们可以得出如下结论:

  1. 广义上来讲,一个snapshot指的就是用当前文件的状态形成的一些相关信息。
  2. 微观上讲,一个snapshot指的是一次提交中的tree结构,tree中记录了每个文件的blob。

以上,便是Git存储文档的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值