Git存储数据的方式
Git 是一个内容寻址文件系统,也就是说他实际上是一个键值对数据库(key-value data store)。Git 存储一份数据,然后返回一个40位的 Hash 值作为键值,通过这个键值,我们就能找到所存储的数据。
- .git/
- objects/
- 9d/
aeafb9864cf43055ae93beb0afd6c7d144bfa4
Hash 值的前两位作为目录,后38位为文件名。文件的内容就是
键值对 的
值 ,也就是 Git 存储的一系列数据。
Git会存储哪些数据?
Git会存储哪些数据呢?文件有三种状态: 未暂存、已暂存和已提交。Git 会存储
已暂存
和
已提交
的文件。同时,当我们提交数据时,当前的提交信息也会被保存下来。所以,Git 会存储两种数据:
-
已暂存
和 已提交
的文件。
- 每次提交时的信息数据,也就是
commit
的注释、作者信息等。
Git如何存储数据?
Git 以键值对的方式存储数据,
键 就是
.git/objects
下的每个目录名及文件名,
值 就是文件的内容,这些值也称为
对象 。而对应于所存储的两种数据,Git 存储的对象有三种:
数据对象
、
树对象
和
提交对象
。
数据对象
Git 使用数据对象来记录每一个文件的数据。比如将一个文件添加到暂存区(index)中,这时,在
objects
目录下就会产生一个数据对象。可以用此命令查看该数据对象:
git cat-file -t <hash>
。
树对象
Git 在每次提交时,会将暂存区的所有数据保存起来,这时会产生一个
树对象 。树对象中的数据记录了在提交前,处于暂存区中的每个文件的状态。这个记录并非将数据都拷贝到当前树对象的文件中,而是记录了暂存区中每个文件的数据对象的
键 值。树对象与数据对象存储的结构关系如下图:
树对象与数据对象的存储关系
提交对象
每次向 Git 仓库中提交文件时,Git 会生成一个提交对象,用以保存当前提交的信息,包括此次提交的父提交对象,作者的信息等。这个提交对象的保存方式也是以 Hash 值为文件名的文件。Git就是将所需要用的到数据转为这三种对象,并且以 Hash 值为文件名的文件的形式,保存在
.git/objects
中。实际上,除了这三种对象,还有第四种对象,即
标签(tags)
对象。保存形式也是一样的。
实际操作
数据存储方式
初始化一个 Git 仓库,当前
.git/objects/
目录如下:
-.git/
- objects/
- info/
- pack/
添加一个文件:
$ echo 'test' > test.txt
将其加入到暂存区:
$ git add test.txt
可以看到
objects/
下多了一个文件夹:
- objects/
- info/
- pack/
- 9d/
aeafb9864cf43055ae93beb0afd6c7d144bfa4
这个就是保存的在暂存区中的文件。将暂存区的文件提交:
$ git commit -m "first commit"
可以看到
objects/
下多了两个文件夹:
- objects/
- 2b/
297e643c551e76cfa1f93810c50811382f9117
- 25/
b94c3791ec86eef47f62bd9ad23e5d5fb9b2b2
- 9d/
aeafb9864cf43055ae93beb0afd6c7d144bfa4
多出来的两个文件,一个是此次提交的树对象,一个是此次提交的提交对象。
三种提交对象
运行以下命令:
$ git cat-file -t 9daeafb9864cf43055ae93beb0afd6c7d144bfa4
blob # 表明是一个数据对象
$ git cat-file -t 2b297e643c551e76cfa1f93810c50811382f9117
tree # 表明这是一个树对象
$ git cat-file -p 2b297e643c551e76cfa1f93810c50811382f9117
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt
## 这个树对象就是我们将 test.txt 文件提交到仓库中生成的树对象。
## 这个树对象存储的是提交前在暂存区中存储的数据,存储的 Hash 值指向了暂存区中的数据。
$ git cat-file -t 25b94c3791ec86eef47f62bd9ad23e5d5fb9b2b2
commit # 表明这是一个提交对象
$ git cat-file -p 25b94c3791ec86eef47f62bd9ad23e5d5fb9b2b2
tree 2b297e643c551e76cfa1f93810c50811382f9117
author Vactor <123456@gmail.com> 838388484 +0800
committer Vactor <123456@gmail.com> 838388484 +0800
first commit
# 以上打印出的就是我们提交时的信息。