1.5. 审视 Blob
让我们来看一下 blue.html
所对应的 blob
对象。使用的还是这个命令 git cat-file
。
复制前几位就可以了。
➜ plumbing-demo git:(main) git cat-file blob cf7bb0e
<!DOCTYPE html>
<html lang="en">
<head>
<title>The Blue Page</title>
<link rel="stylesheet" href="style.css" />
<meta charset="utf-8" />
</head>
<body>
<h1 style="color: #00F">The Blue Page</h1>
<p>Blue is the color of the sky.</p>
<p><a href="index.html">Return to home page</a></p>
</body>
</html>
可以看出它展示出了 blue.html
里面所有的内容。这就是一个普通的 HTML 文件,说明了 blob
确实是普通的数据文件。
注意,这个 blob
是纯内容的,它是不含有文件名的,也就是说blue.html
这个名字不是存储在这个 blob
文件里面的,而是存储在包括这个 blob
文件所在的 tree 里面的。
从前面基础,我们可以回忆到一个 SHA-1
校验和确保了一个对象的内容是绝对不会丢失的,除非你故意告诉Git,你要去把它删掉。校验和是通过对象的内容来产生一个唯一的字符串。它不仅可以作为一个 ID, 还可以保证一个对象不会被默默地损坏。一旦你更改了它的内容,就会产生一个不同的 ID。
对于 blob
对象来说,这种机制还有另外的好处,因为如果两个 blob
有同样的内容,那么他们就会有同样的 ID,而 Git 在不同的 tree
之间必须分享这些 blob
。 比如 blue.html
这个文件从它创建开始之后就一直没有被修改过。所以我们的这个仓库就只有一个 blob
是跟它相连的。随后所有的这个 tree
都直接引用它,而不是对每一个 tree
对象都创建一个重复的 blob
。通过这种方式, git 就极大地减小了仓库的体积。有了这个认识之后,我们就可以将我们的 git 对象图改变为下面这个样子。
从这个图上我们就可以看到一个 commit 对应的是一个 tree
,一个 tree
下面有多个 blob
对象。但一个 blob
对象有可能是只属于一个 tree
也可能是属于多个 tree
,在这种情况下面,这一个 blob
它是被多个 tree
所分享的,他们都只是通过一个指针指向这个 blob
,而并不是说每一个 tree
都包含了这个 blob
对象,这样的话就会大大减少仓库的体积。然而只要你在一个文件里面修改了一个字符, git 就会创建一个全新的 blob
对象,因为它的内容变化会产生一个新的 SHA-1
校验和。