
Git儲存結構
Git有四大元件,分別是:
- Tag
- Commit
- Tree
- Blob
當git初始化後,目錄下就生成了.git資料夾,存放著與git相關的所有內容,我們看下目錄下具體的內容:

所有的元件都存放在objects資料夾中:

Blob元件
當我們執行git add README.md
後,資料夾內容如下:

我們可以看到,目錄中多了83目錄,即blog元件,83目錄中有檔名是一串UUID的檔案,當我們執行git add將檔案變為staged狀態後,就會在objects目錄建立一個元件,元件都是以hash的二進位制方式進行儲存,元件的名稱為資料夾名稱+檔名稱,所有上面的blob元件的名字即為83920ba13f0cd4e0046337313c1f0a1cfc676ad4
,這個名字是唯一的。
當修改README.md後再次執行git add,發現,objects目錄中又多了一個blob元件:

注意:如果兩個檔案的內容一樣的話,執行git add的時候,只會生成一個blob元件,不會是兩個。blob元件是在程式碼提交到Stage區域的時候生成的,而且是以內容來生成一個位元組碼檔案。
可以通過git hash-object來查詢檔案的hash碼:

Commit元件
剛剛我們已經執行了兩次git add,下面我們將變動提交,執行git commit:
git commit -m "init"
複製程式碼

可以看到,objects中多了兩個資料夾,b6和da,這兩個是什麼呢?我們先用git log檢視下提交日誌:

可以看到,commit的id為da7b2dd822e576db1cfb0e546a9de57fc8cfbe8b
,所以da資料夾為commit元件,那麼b6是什麼呢?
Tree元件
b6是tree元件,每次commit時,首先會建立commit元件,然後將涉及的檔案資訊建立tree元件,我們可以用git cat-file -p命令檢視commit元件:

可以看到,通過git cat-file -p命令檢視commit元件,可以看到tree元件,我們用git cat-file -p來檢視tree元件:

可以看到,tree元件中記錄了檔案的基本資訊。
底層執行流程
我們總結下git底層的執行流程:

- 當我們新增或者修改了檔案並且add到stage區之後,會根據檔案內容建立不同的blob
- 當進行提交之後馬上建立一個tree元件把需要的blob元件新增進去,之後再封裝到一個commit元件中完成本次提交。
- 在將來進行reset的時候可以直接使用git reset --hard xxxxx可以恢復到某個特定的版本
- 在reset之後,git會根據這個commit元件的id快速的找到tree元件,然後根據tree找到blob元件,之後對倉庫進行還原
我們看到,git的整個過程都是以hash和二進位制進行操作,所以git執行效率非常之高。
