解剖 .git 資料夾 part. 2 - Blob Object
在前面的 解剖 .git 資料夾 part. 1 - Git Init 我們已經初步瞭解了 .git
資料夾初始化後的結構,但是其中 objects
這個資料夾是空的,就讓我們來看看 執行 git add
後是如何將檔案存放在 objects
資料夾下
Blob object 介紹
由於目前我們還沒有任何的檔案,讓我們新增一個 README.md
echo "This is readme." > README.md
再來執行 git add README.md
來將他加到 git 的索引裡,完成後 git status
的結果應該會像下面這樣:
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
這時候我們可以來看一下 .git/objects
下的檔案長什麼樣子
objects/
├─ pack/
├─ info/
└─ 52/
└─ cb6cdb81a64344370c918a301eb153035f915a
blob object 內容
這時候多了一個名字叫 52
的資料夾,底下有一個檔案叫 cb6cdb81a64344370c918a301eb153035f915a
,如果你把他打開會發現內容是看不懂的
$ xxd .git/objects/52/cb6cdb81a64344370c918a301eb153035f915a
00000000: 7801 4bca c94f 5230 3463 08c9 c82c 5600 x.K..OR04c...,V.
00000010: a2a2 d4c4 94dc 543d 2e00 5ee3 0781 ......T=..^...
原因是所有在 object file 下的檔案都會經過 zlib
壓縮後存放,解壓縮後我們可以看到 object file 的內容是由以下的結構所組成
blob
+空格
+檔案大小
+zero btye
+原始檔案的內容
比較特別的是檔案大小會用十進位來儲存,會直接寫 1
和 6
的 ASCII code 而不是十六進位的 00 10
(我們檔案在最後面有換行符號,所以 size 是 16)
$ openssl zlib -d -in .git/objects/52/cb6cdb81a64344370c918a301eb153035f915a | xxd
00000000: 626c 6f62 2031 3600 5468 6973 2069 7320 blob 16.This is
00000010: 7265 6164 6d65 2e0a readme..
git 其實也有提供工具來幫忙解壓縮和印出內容
我們需要先得到完整的 object hash 兩碼資料夾
+ 檔名
= 52cb6cdb81a64344370c918a301eb153035f915a
當我們有了 object hash 之後可以用
git cat-file -t <HASH>
來印出 object 類型blog
git cat-file -p <HASH>
來印出內容This is readme.
git cat-file -s <HASH>
來印出檔案大小16
blob hash 由來
這個長長的 hash 其實是用未壓縮的檔案內容做 SHA-1 hash 之後得到的結果,我們可以用 sha1sum
指令來測試
$ openssl zlib -d -in .git/objects/52/cb6cdb81a64344370c918a301eb153035f915a | sha1sum
52cb6cdb81a64344370c918a301eb153035f915a *-
由於是依照檔案內容來計算出來的 hash 當 object 檔名,如果有內容完全一樣的檔案就可以直接共用來省空間,另外用兩碼來切分資料夾也可以避免在同一個資料夾中有過多的檔案,有助於提高尋找和管理的效率
BTW 如果想要用 SHA-256 演算法來算 object hash 也是可行的,只要在 git init 的時候用 --object-format=sha256
來指定即可
這篇就先講到這邊,我們接下來可以來看一下 .git/index
這個檔案的內容
如果覺得內容有幫助可以給個拍手~
留言
張貼留言