解释 Git 中的 BLOB 对象和树对象。


Git 使用一系列 BLOB 和树对象来存储项目工作目录的内容。每当我们执行提交操作时,Git 内部会创建一系列树和 BLOB,这是项目文件夹结构在提交时的二进制表示。

什么是 BLOB?

BLOB 代表 **Binary Large Object**(大型二进制对象)。Git 中每个版本的档案都表示为一个 BLOB。BLOB 保存档案的数据,但不包含任何关于档案的元数据,甚至不包含档案名称。

为了理解 BLOB,让我们来看一个例子。

  • 创建 3 个文本文件:“file1.txt”、“file2.txt” 和 “file3.txt”。前两个文件将包含相同的内容,而第三个文件将有不同的内容。

$ git init                    // initialize a repo
$ echo hello>file1.txt        // create a file and enter some content
$ echo hello>file2.txt        // create a file and enter the same content
$ echo hello world>file3.txt  // create a file and enter some content
  • 让我们将这些文件添加到暂存区。暂存这些文件将在“.git\objects”文件夹下创建 BLOB。在这个例子中,我们每次暂存文件时都会列出“.git\objects”文件夹中的内容。

$ git add file1.txt    // stage the file
$ ls .git/objects/     // list contents
$ git add file2.txt
$ ls .git/objects/
$ git add file3.txt
$ ls .git/objects/

ls 命令的输出如下所示。

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ git add filel.txt

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ Is .git/objects/
ce/ info/ pack/

dell@DESKTOP-N96LNR5 MINGW64 /e/tut_repo (master)
$ git add file2.txt

dell@DESKTOP-N961NR5 MINGw64 /e/tut_repo (master)
$ Is .git/objects/
ce/ info/ pack/

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ git add file3.txt

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ Is .git/objects/
3b/ ce/ info/ pack/

当“file1.txt”和“file3.txt”被暂存时,创建了名为“ce”和“3b”的文件夹。但是,当“file2.txt”被暂存时,没有创建新的文件夹。这是因为“file1.txt”和“file2.txt”的内容相同。

  • 现在让我们看看“ce”和“3b”文件夹的内容。

$ ls .git/objects/ce
$ ls .git/objects/3b

输出显示这些文件夹包含表示为 SHA1 哈希的 BLOB 对象。

dell@DESKTOP-N961NRS MINGW64 /e/tut_repo (master)
$ Is .git/objects/ce
013625030ba8dba906f756967f9e9ca394464a

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ Is .git/objects/3b
18e512dba79e4c8300dd08aeb37f8e728b8dad

现在让我们验证文件的类型及其内容。

$ git cat−file −t ce01
$ git cat−file −p ce01
$ git cat−file −t 3b18
$ git cat−file −p 3b18

从输出中可以看出,尽管我们添加了 3 个文件,但 Git 创建了 2 个 BLOB。这是因为前两个文件的内容相同。从输出中可以看出,BLOB 只存储文件的內容,而不存储文件名。

//output of cat−file −t ce01
blob
//output of cat−file −p ce01
hello
//output of cat−file −t 3b18
blob
//output of cat−file −p 3b18
hello world

什么是树?

树就像一个目录。Git 中的每个提交都指向一个树对象,该对象又引用 BLOB。树对象记录以下内容:

  • BLOB 标识符

  • 路径名称

  • 该目录中所有文件的元数据

树可以递归地引用其他树对象或子树。因此,树构建了文件和子目录的完整层次结构。就像 BLOB 一样,树也可以在“.git/objects”文件夹下查看。

让我们通过之前的例子来理解树。我们创建了三个文件并将它们全部添加到暂存区。让我们使用**git status**命令来验证这一点。让我们也将所有更改提交到存储库。

$ git status -s // verify status
$ git commit -m 'initial commit' // commit to the repo

状态指示已暂存 3 个文件。发出 git commit 命令后,将创建一个哈希值为“84a00db”的提交。

dell@0ESKTop-N961NR5 MINGW64 /e/tut_repo (master)
$ git status -s
A fiIe1.txt
A file2.txt
A file3.txt
dell@DESKTOP-N961NR5 MINGW64 /e/tut—repo (master)
$ git commit -m 'initial commit'
[master (root-commit) 84aOOdb) initial commit
3 files changed, 3 insertions(+)
create mode 100644 file1. txt
create mode 100644 file2. txt
create mode 100644 file3.txt

我们例子的内部结构可以表示如下:

上图显示提交“84a0”指向一个树,它是项目的根文件夹。根文件夹有 3 个作为 BLOB 存储的文件。前 2 个文件指向同一个 BLOB,因为它们的内容相同。树对象保存对所有 BLOB 的引用。如果我们在当前项目中创建新的文件夹,则这些文件夹将作为根项目树“e115”的子树创建。

让我们验证 objects 文件夹以查看是否创建了任何提交对象或树对象。这可以使用 ls 命令来查看。

$ ls .git/objects
$ ls .git/objects/84
$ ls .git/objects/e1

输出显示文件夹“84”表示一个提交,“e1”将是与其关联的树。这些文件夹有一个由 SHA1 哈希表示的指针文件。

dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ Is .git/0bjects/84
aOOdb87bb5c69926b3343a564db1b3a96a389d
dell@DESKTOP-N961NR5 MINGW64 /e/tut_repo (master)
$ Is .git/objects/el
1588b4a639bb90b18268b7e26f243ba31706fd

现在让我们使用**cat-file**命令验证这些指针文件中的内容。

$ git cat−file −p 84a0
$ git cat−file −p e115

从输出中可以看出,提交 (84a0) 指向一个树,它是项目的根文件夹。

tree e11588b4a639bb90b18268b7e26f243ba31706fd
author Kiran 1612777422+0530
committer Kiran 1612777422+0530
initial commit

项目的根文件夹包含三个作为 BLOB 存储的文件。

dell@DESKTop-N961NR5 MINGW64 /e/tut_repo (master)
$ git cat
−file −p e115
100644 blob ce013625030ba8dba906f756967f9e9ca394464a file1.txt
100644 blob ce013625030ba8dba906f756967f9e9ca394464a file2.txt
100644 blob 3b18e5L2dba79e4c8300dd08aeb37f8e728b8dad file3.txt

更新于:2021年2月20日

2K+ 次浏览

启动你的 职业生涯

完成课程获得认证

开始
广告