解釋 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