树对象(tree)—— 保存文件名和目录关系
树对象主要解决2个问题,:文件名的保存和文件目录关系的保存
就像下面这样
下面我们就来模拟一下构建上面这颗树,也就是模拟保存这3个文件,其中的"bak"是一个目录,下面有一个文件
首先可以看到,我们一共需要保存的是3个文件,new.txt 、 内容为version 2的 test.txt 和内容为version 1的 test.txt。其中我们上面已经把version 1的 test.txt写入到Git仓库了。
Git是怎么创建树对象的呢?
Git 根据某一时刻暂存区(即 index 区域)所表示的状态创建并记录一个对应的树对象,如此重复便可依次记录(某个时间段内)一系列的树对象。而暂存区里保存就是我们add进去的文件和目录。
而我们之前的text.txt是直接存入到Git数据库里面了,没有在暂存区,所以先要把这个文件读到暂存区里来
我们可以用 update-index 命令更新暂存区(跟我们做git add
操作是一样的道理)
git update-index --add --cacheinfo 100644 83baae61804e65cc73a7201a7252750c76066a30 test.txt
- add :表示写入,因为文件不在暂存区中
- cacheinfo:表示是从Git数据库中取文件,因为我们的文件不在工作目录,而是在Git数据库中
- 100644:表示是普通文件,此外还有
100755
,表示一个可执行文件;120000
,表示一个符号链接 - 后面就是文件的SHA-1值和文件名
好的,现在我们已经把前面的内容更新到暂存区了。
然后我们就可以用 write-tree 命令生成一个树对象
git write-tree
//输出
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
我们可以验证一下它确实是一个树对象(git cat-file -t命令可以查看对象的类型):
git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
//输出
tree
经过上面的步骤,我们就把右边的那个树对象创建完毕了。
实际上,上面已经解决了一个问题,就是文件名的保存。
git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
//输出
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
这里我们再快速创建剩下的部分,直接新建new.txt
和更新text.txt
,然后用git add
添加到暂存区并生成一个新的树对象
echo 'new file' > new.txt
echo 'version 2'> text.txt
git add .
git write-tree
下面我们来看看怎么解决目录保存的问题,也就是树和树关联起来
//首先把前面的把那个树对象写入到暂存区,其中bak就表示目录名
git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
//然后生成一个新的树对象
git write-tree
//输出
9f2f42e85a6648e5b5f48e1a6f154999e06b9a31
然后我们就可以来看看这个新的树对象了:
git cat-file -p 9f2f42e85a6648e5b5f48e1a6f154999e06b9a31
//输出
040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a text.txt
可以看到,目录就对应一个树对象,这样保存目录的问题就解决了。
数据对象和树对象用于保存数据和文件名和目录,我们还需要记录是谁保存的这些数据以及时间和原因等信息,而这些信息就需要第三个对象——提交对象。下一次我们就来看看提交对象