由于工作中使用git作為版本管理,之前對(duì)git的了解不多,特別是底層方面的原理方面的知識(shí)。為了能更好的使用git,有必要學(xué)習(xí)并梳理下相關(guān)知識(shí)。
步入正題:
git的文件結(jié)構(gòu)
執(zhí)行g(shù)it init 初始化后,會(huì)在.git文件夾下會(huì)創(chuàng)建多個(gè)目錄,每個(gè)文件夾功能劃分的很清晰。

git的存儲(chǔ)方式
Git 是一套內(nèi)容尋址文件系統(tǒng).通過(guò)鍵值對(duì)的方式存儲(chǔ)和查找。
下面操作一遍,直觀的看到整個(gè)過(guò)程,以便理解。
- 首先,創(chuàng)建一個(gè)內(nèi)容對(duì)象
$ echo "小明的文件" | git hash-object -w --stdin
5c98f8a9221e5336f68c7575cd238b48875137c6
| 命令/參數(shù) | 說(shuō)明 |
|---|---|
| echo | 將字符串輸出到終端 |
| git hash-object | 創(chuàng)建一個(gè)blob(二進(jìn)制大對(duì)象), 可指定其他類型,不一定是blob。 |
| --stdin | 從標(biāo)準(zhǔn)終端中讀取輸入,代替從文件讀取, 這里讀取的是由echo命令輸出到終端的字符串。 |
| -w | 把blob對(duì)象寫入數(shù)據(jù)庫(kù) |
參考:https://git-scm.com/docs/git-hash-object
- 查看剛才存儲(chǔ)的數(shù)據(jù)
$ find .git/objects -type f
.git/objects/5c/98f8a9221e5336f68c7575cd238b48875137c6
| 命令/參數(shù) | 說(shuō)明 |
|---|---|
| find | 查找目錄下文件 |
| -type f | 指定查類型為普通文件 |
參考:http://man.linuxde.net/find
可以見(jiàn)到文件名稱為數(shù)字和字母組成的字符串。這個(gè)是根據(jù)文件內(nèi)容和頭信息(Header),通過(guò)SHA-1算法計(jì)算得出的40位十六進(jìn)制校驗(yàn)和。
| 校驗(yàn)和 | 5c98f8a9221e5336f68c7575cd238b48875137c6 |
| 存儲(chǔ)路徑 | 5c/98f8a9221e5336f68c7575cd238b48875137c6 以校驗(yàn)和前兩位作為子路徑創(chuàng)建文件夾, 以校驗(yàn)和后38位作為文件名生成文件。 |
SHA-1是一種加密哈希函數(shù)(cryptographic hash function)。SHA-1將文件中的內(nèi)容通過(guò)其hash算法生成一個(gè)160bit的報(bào)文摘要,即40個(gè)十六進(jìn)制數(shù)字(每個(gè)十六進(jìn)制數(shù)字占4位)。它幾乎可以保證,如果兩個(gè)文件的SHA-1值是相同的,那么它們確是完全相同的內(nèi)容(類似于生活中的指紋識(shí)別);SHA-1主要有兩種用途,一個(gè)是加密,一個(gè)是數(shù)據(jù)完整性校驗(yàn)。Linux kernel開(kāi)創(chuàng)者和Git的開(kāi)發(fā)者——Linus說(shuō),Git使用了SHA-1并非是為了安全性,而是為了數(shù)據(jù)的完整性。理論上SHA-1會(huì)在2^51攻擊下實(shí)現(xiàn)哈希碰撞,所以也不是完全的安全。
- 通過(guò)校驗(yàn)和作為鍵值 解讀文件
$ git cat-file -p 5c98f8a9221e5336f68c7575cd238b48875137c6
小明的文件
| 命令/參數(shù) | 說(shuō)明 |
|---|---|
| git cat-file | 讀取對(duì)象信息 |
| -p | 根據(jù)對(duì)象的類型打印其信息 |
參考:https://git-scm.com/docs/git-cat-file
模擬bolb對(duì)象存儲(chǔ)流程

以上,說(shuō)明了git的數(shù)據(jù)存儲(chǔ)的基本方式。主要步驟:
- 使用SHA-1算法根據(jù)其原始內(nèi)容和頭信息(頭信息格式"blob #{content.length}\0")生成唯一的40位校驗(yàn)和。
- 以校驗(yàn)和前兩位創(chuàng)建文件夾、校驗(yàn)和后38位作為文件名。
- 對(duì)拼接后的內(nèi)容壓縮后存儲(chǔ)。
下面是創(chuàng)建文件,修改文件,恢復(fù)文件的相關(guān)過(guò)程。
- 重新創(chuàng)建一個(gè)倉(cāng)庫(kù)并創(chuàng)建一個(gè)文件
$ echo '小明該吃午飯了' > test.txt
$ git hash-object -w test.txt
efbd70f46da0d1852de88c58aebc86616beecdaf
- 修改文件再保存
$ echo "小明打算去吃個(gè)泡面" > test.txt
$ git hash-object -w test.txt
26aab56c7d1f9bd962b28f78ce61f021b221d317
- 查看已保存的內(nèi)容
$ find .git/objects -type f
.git/objects/26/aab56c7d1f9bd962b28f78ce61f021b221d317
.git/objects/ef/bd70f46da0d1852de88c58aebc86616beecdaf
- 恢復(fù)到第一個(gè)版本
$ git cat-file -p efbd70f46da0d1852de88c58aebc86616beecdaf > .git/test.txt
$ cat .git/test.txt
小明該吃午飯了
git會(huì)記錄每個(gè)版本的修改,根據(jù)校驗(yàn)和可恢復(fù)到相應(yīng)的版本。
小結(jié):這個(gè)過(guò)程中包括文件創(chuàng)建、文件修改、文件恢復(fù),跟我們平時(shí)工作中使用的高級(jí)命令功能很相似。git會(huì)把整個(gè)過(guò)程轉(zhuǎn)化為底層操作,同時(shí)對(duì)用戶透明。
相關(guān)引用參考:
http://smilejay.com/2012/08/git-commit-sha-1/
https://git-scm.com/book/zh/v1/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-Git-%E5%AF%B9%E8%B1%A1