Git工作原理

按照官方文檔的描述,Git是這樣定義的

  • 內(nèi)容尋址(content-addressable)文件系統(tǒng),在此之上提供了一個(gè)VCS用戶界面
  • Git采用HashTable的方式進(jìn)行查找,通過簡(jiǎn)單的存儲(chǔ)鍵值對(duì)的方式來實(shí)現(xiàn)內(nèi)容尋址,key是文件頭和內(nèi)容組成的40位hash值,value是壓縮過后的文件內(nèi)容
    當(dāng)然,這句話寫得并不是很容易讓人明白,通過查看git的目錄結(jié)構(gòu)以及細(xì)致地分析一次Git提交可以更好地幫助理解Git

.git目錄

.git目錄是Git的核心,每一個(gè)變動(dòng)都會(huì)存儲(chǔ)在.git文件夾中,Git的相關(guān)命令本質(zhì)上也是讀取.git文件夾下的內(nèi)容
.git目錄下有幾個(gè)重要的文件/文件夾

  • config文件,主要存儲(chǔ)項(xiàng)目的一些配置信息
  • objects文件夾, 存儲(chǔ)git對(duì)象
  • HEAD文件,記錄當(dāng)前的頭指針
  • index文件,存儲(chǔ)暫存區(qū)的信息
  • refs文件夾, 存儲(chǔ)分支的指針

git對(duì)象

提交和文件是Git中的主要組成,也叫g(shù)it對(duì)象,Git中的許多命令都和git對(duì)象有關(guān)
git對(duì)象分為下面3類


image.png

git對(duì)象存儲(chǔ)在.git目錄下的objects文件夾中,Git會(huì)將git對(duì)象壓縮成二進(jìn)制文件,git對(duì)象的文件名即sha-1算法得到的hash值,按照2/38的形式保存(前兩位是文件夾的名稱,剩下38位是文件名,這樣做可以防止文件夾的內(nèi)容過多,提高查找效率)

對(duì)于commit對(duì)象,hash值也被稱為commitid

可以使用以下命令查看git對(duì)象中的內(nèi)容

git cat-file -p <hash>

通過查看三種git對(duì)象的內(nèi)容,不難發(fā)現(xiàn)如下的組織關(guān)系


image.png
  • 每個(gè)commit的對(duì)象包含了tree和blob對(duì)象的hash
  • 每個(gè)tree對(duì)象包含了blob文件的hash
  • 每個(gè)blob對(duì)象是真正文件的二進(jìn)制保存

其實(shí)可以吧hash看成每個(gè)對(duì)象的指針,Git通過指針將眾多git對(duì)象串聯(lián)起來,來實(shí)現(xiàn)對(duì)項(xiàng)目的版本控制

從Git命令看一次提交的完整過程

用戶通過Git命令讀寫.git文件夾,達(dá)到獲取信息或變更版本的目的

Git一開始被設(shè)計(jì)成供VCS使用的工具集合而不是一整套用戶有好的VCS,它還包含了許多的底層命令,一般被稱為plumbing命令(底層命令),而用戶日常使用Git命令被稱為porcelain命令(高層命令),porcelain命令實(shí)際是是對(duì)plumbing命令的封裝

image.png

一次完整的提交過程會(huì)包含如下過程

  • 保存二進(jìn)制對(duì)象(即生成blob對(duì)象)
  • 寫入暫存區(qū)
  • 保存目錄結(jié)構(gòu)(生成tree對(duì)象)
  • 提交目錄結(jié)構(gòu) (指定上一個(gè)提交的hash并生成commit對(duì)象)
  • 更新分支(更新分支指向的hash)

使用porcelain命令的話是非常簡(jiǎn)單的

git add <file>
git commit -m "commit message"

如果使用plumbing命令就會(huì)復(fù)雜很多,但是可以更好地理解其背后的工作原理

git hash-object -w <file>
git update-index <file>
git write-tree
echo "commit message" | git commit-tree writetreehash -p <last commit hash>
echo <commit hash> .git/refs/heads/<branchname>

Git分支和HEAD

通過前文的內(nèi)容不難發(fā)現(xiàn),每次生成的commit對(duì)象會(huì)包含上一個(gè)commit對(duì)象的hash,即當(dāng)前的commit包含上一個(gè)commit的指針,許多個(gè)commit對(duì)象串聯(lián)起來就形成了分支

所以,Git的分支本質(zhì)上是指向commit對(duì)象的可變指針

而HEAD代表當(dāng)前commit的指向,.git/refs/heads/<branchname>文件的內(nèi)容就是該commit對(duì)象的hash

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容