iT邦幫忙

2021 iThome 鐵人賽

DAY 17
1
Modern Web

【Git】從零開始學習 Git - 30 天的學習筆記系列 第 17

Day17|【Git】存在 .git 目錄裡的東西 - Blob 物件與 Tree 物件(上)

Git 有四種 type (類型) 的物件:blob、tree、commit 和 tag。

本篇主要先來講解 Blob 物件與 Tree 物件。

本篇會使用到兩個過去沒使用的指令:git hash-objectgit cat-file -t
未來有機會可以介紹!


Blob 物件(Binary large object)

說明:Git 將檔案內容轉成二進制,並產生 SHA-1 編號後儲存的物件。

產生時機:git add 加至暫存區時,在 .git 目錄裡產生一個 Blob 物件,並依照規則擺放在它的目錄裡。

用途:存放檔案的「內容」。

⚠️ 注意:此處指的是檔案裡面的內容,即可能編輯的東西,而非檔案本身。

🛠 實際操作|建立 Blob 物件 - 建立一個檔案並加入至 Git 控管

  1. 首先先建立一個工作目錄,並進行 Git 版本控制,執行 git init 初始儲存庫。

    $ git init # 初始化儲存庫
    

    https://ithelp.ithome.com.tw/upload/images/20211001/201410108WR3rCgkSL.png

    初始化新的數據庫時,Git 會在 .git 目錄中初始化 objects 目錄,並在裡面建立 pack 和 info 子層的空目錄。

    https://ithelp.ithome.com.tw/upload/images/20211001/201410107ucHA3TYIz.png

  2. 假設今天我們建立了一個 demo.html 檔案,並在檔案裡加上內容是 " hello world ! " 字串

    $ touch index.html # 新增一個 index.html 檔案
    

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010tjt12TrVQt.png

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010duzU02Fm9m.png

    前幾篇的文章我們可以知道,目前檔案還沒有被 Git 控管,因此我們可以透過指令將檔案加至暫存區。

  3. 輸入指令執行將檔案加至暫存區,並檢查狀態

    $ git add . # 將所有檔案加入暫存區
    $ git status # 檢查檔案狀態
    

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010AdXHrswM3k.png

    👉 這時候,Git 會在 .git 目錄下建立 blob 物件用來儲存檔案內容。

    可以從 objects 目錄中發現,多了兩個資料夾。更進一步查看會發現是個 38 字元的檔案。

    資料夾的 2 個字元與檔案的 38 個字元合起來代表這個 Blob 物件的 SHA-1 值,它是透過「規則」計算出來的。

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010wwlaVZG0xk.png

  4. 也可以透過手動執行 git hash-object 指令來計算

    $ echo 'hello world!' | git hash-object -w --stdin # 將資料儲存在 .git 目錄中,並取得 SHA-1 編號
    

    -w 參數

    將物件加入 .git/objects 目錄內,並輸出相對應的 SHA-1 值

    如果沒有加上 -w 參數,只會輸出 SHA-1 值,並不會儲存物件

    --stdin 參數

    從 stdin 讀取內容(stdin - standard input, 標準輸入)

    如果沒有使用 --stdin 參數,hash-object 指令預設會從檔案中讀取,因此需要在指令後面加上指定的檔案路徑。

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010affI4NFovp.png

    https://ithelp.ithome.com.tw/upload/images/20211001/201410105djOKAl4LN.png

    執行hash-object 指令後,會出現 40 個字元,這就是 SHA-1 值,是由儲存的內容和 header 資訊所計算出來的。

    目錄規則:

    子目錄 - 前 2 個字元

    檔名 - 剩餘的 38 字元

💡 使用 2 個字元作為子目錄,是避免讓 .git/objects 目錄因為檔案過多而降低效能。

  1. 這個檔案內容因為已經被壓縮過,所以我們如果使用一班的文字編輯器是無法得知內容,不過可以使用 git cat-file 指令察看物件資訊

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010DMXJ3UVVSO.png

    $ git cat-file -t a0423 # 查看物件資訊(型態)
    

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010iuwcc9pHaN.png

    -t 參數,代表要查看的是內容的物件型態,因此得到的回饋會是 blob 物件

    如果想要看這個物件的內容的話,可以改用 -p 參數。

    $ git cat-file -p a0423 # 查看物件資訊(內容)
    

    https://ithelp.ithome.com.tw/upload/images/20211001/20141010cMWZmqnDVq.png

    這時候 Git 的回報就是當初我手動儲存的文字內容啦!

總結上述操作得知:

  1. 使用 git add 將檔案加至暫存區後,會建立一個 Blob 物件,並根據物件的內容計算出 SHA-1 值。
  2. SHA-1 值前 2 個字元作為子目錄名稱,剩餘 38 個字元作為檔案名稱。
  3. 檔案內容為 Git 壓縮演算法後,將內容壓縮之後的結果。

Blob 物件的檔名由 SHA-1 演算法決定;Blob 的內容則是壓縮演算法決定。


Tree

有了 Blob 物件可以存內容之後,Git 也提供了可以存檔名、資料夾名稱的物件,此物件及為「Tree 物件」。

關於 Tree 物件的說明:

  • 儲存檔案的名稱、資料夾名稱、檔案權限等
  • 透過 Tree,找到子目錄、子子目錄的檔案內容、名稱

Tree 物件與 Blob 物件相同,都是以 SHA-1 雜湊值作為檔名,儲存二進制內容。但兩著的差異在於,Blob 物件主要是儲存我們的檔案「內容」,而 Tree 物件則是儲存「檔名」,而 Tree 物件裡不一定只有包著 Blob 物件,同時也可以包含另一個 Tree 物件。

了解 Tree 物件的內容後,我們大致可以了解 Tree 可以幫助我們儲存檔案的名稱目錄的名稱檔案權限,也因為 Tree 物件同時可以紀錄 Tree 物件與 Blob 物件之間的關聯性,因此我們可以透過 Tree 物件來找到子目錄以下的一些檔案內容或檔名。

下圖說明 Tree 物件與 Blob 物件之間的關聯性:

https://ithelp.ithome.com.tw/upload/images/20211001/20141010hE96j1i606.png


總結整理:

Blob 儲存檔案「內容」、Tree 儲存檔案「名稱」


上一篇
Day16|什麼是 HEAD ?
下一篇
Day18|【Git】存在 .git 目錄裡的東西 - Commit 與 Tag(下)
系列文
【Git】從零開始學習 Git - 30 天的學習筆記30

尚未有邦友留言

立即登入留言