淺談 Git 資料結構
TLDR
- Git 的所有資料與版本控制紀錄皆儲存在
.git目錄中,刪除該目錄即等同刪除本機版控。 objects資料夾以 SHA-1 哈希值儲存 Blob(檔案內容)、Tree(目錄結構)與 Commit(提交資訊)三種物件。refs資料夾儲存分支與 Tag 的指標,它們本質上只是指向特定 Commit HASH 的檔案。logs資料夾記錄了 HEAD 與分支的變動歷史,可透過git reflog查詢並用於還原誤刪的 Commit。index檔案為二進位檔,記錄了git add後的暫存區快照。HEAD檔案記錄當前工作目錄所處的分支或 Commit 位置。- 分支與 Tag 僅是指向 Commit 的指標,Git 的歷史紀錄是透過 Commit 物件中的指標鏈(指向前一個 Commit)所構成。
.git 目錄結構解析
Git 的所有儲存資料都存在於 .git 資料夾裡。以下為該目錄下各核心元件的用途與運作機制。
資料夾結構
- hooks:存放各種客製化腳本,在 Git 操作(如
commit、push、merge)的特定時機自動執行,適用於自動化測試或檢查程式碼風格。 - info:儲存輔助性資訊,其中
exclude檔案用於定義本機排除規則,與.gitignore用途相同,但僅適用於單一開發者環境。 - logs:記錄引用(如 branch、HEAD)的更新歷史。
- 什麼情況下會遇到這個問題:當執行
git reset --hard或git rebase -i導致 Commit 記錄遺失時,可透過git reflog讀取此處紀錄並進行還原。
- 什麼情況下會遇到這個問題:當執行
- objects:儲存所有 Git 資料物件(Blob、Tree、Commit)。
- 結構:以 SHA-1 哈希值前兩個字元作為目錄,後 38 個字元作為檔案名稱。
- 物件生成機制:執行 Commit 時會產生三種物件:
- Blob 物件:儲存檔案的實際內容。
- Tree 物件:儲存目錄結構與對應的 Blob 物件哈希值。
- Commit 物件:儲存提交資訊(包含 Tree 哈希、上一個 Commit 哈希、作者與訊息)。
- refs:儲存分支與 Tag 的指標。
heads:儲存本機分支。remotes:儲存遠端分支。tags:儲存 Tag 名稱。
關鍵檔案說明
- COMMIT_EDITMSG:記錄上一次 Commit 的訊息。執行
git commit或git commit --amend時會開啟此檔案供編輯。 - config:儲存該儲存庫的專屬 Git 設定。
- index:二進位檔案,記錄最新一次 Commit 後的快照及
git add加入的檔案資訊。 - HEAD:記錄當前檢出的分支或 Commit。若指向分支,內容為
ref: refs/heads/分支名;若處於分離 HEAD 狀態,則直接儲存 Commit HASH。 - ORIG_HEAD:儲存執行
git reset或git merge等破壞性操作前的 HEAD 狀態,用於還原。 - FETCH_HEAD:標註每次
git fetch的紀錄,格式如下:text{Commit SHA-1} [not-for-merge] branch '{分支名稱}' of {遠端儲存庫網址}- 什麼情況下會遇到這個問題:當
git fetch執行後,若未觸發 Merge 行為,該節點會標記為[not-for-merge]。
- 什麼情況下會遇到這個問題:當
分支與版本控制的本質
由 Git 的資料結構可知,分支與 Tag 本質上僅是指向特定 Commit 物件的指標。
- 分支 (Branch):隨每次 Commit 自動更新指向的指標。
- 標籤 (Tag):指向固定 Commit 物件的指標。
Git 的歷史紀錄是透過 Commit 物件內部儲存的「上一個 Commit HASH」鏈結而成。當執行 git reset 或 git rebase 時,雖然分支指標移動了,但舊的 Commit 物件依然存在於 objects 資料夾中,這也是為什麼透過 git reflog 可以找回歷史紀錄的原因。
異動歷程
- 初版文件建立。
- 儲存庫根目錄底下的「.gitconfig」無法生效,所以移除可作為版控的相關描述。