20150917 [學習筆記] Git版本控制(5)
[基本概念] 物件的概念
  • Git 裡的「物件」十分重要,雖然在操作 Git 指令的過程中通常不太需要直接接觸這些檔案,不過了解這些物件的存在,有助於理解 Git 的運作模式與 設計概念。
 
[內容摘要] Git 資料結構
  • (一)物件資料庫
  • (二)物件類型
  • (三)物件結構的優點
 
 
 
 

(一)物件資料庫

  • 「物件」是一種「不可變的」 (immutable) 檔案類型,儲存在「物件儲存區」的檔案只進不出,也不會被修改。
  • [ 原因 ]  如果竄改檔案內容,新的內容運算出來的 SHA1 雜湊值會與原有物件的檔名不一樣,會導致 Git 無法繼續執行。(有保護作用)
  •  
  • 物件(blob 物件與 tree 物件)都會儲存在一個所謂的「物件儲存區」 (object storage) 之中,預設在「儲存庫」的 objects 目錄下:
  • 每一個「物件」,都是以「檔案內容」進行 SHA1 雜湊運算出一個 hash 值,並用這個 hash 值當作物件的名稱。
  • [ 例子1 ]  「檔案內容」: 8a6b275638f3cf164395e65066a1132bb36b7896
  • (1)前兩個字元(8a)當作目錄
  • (2)剩下的值(6b275638f3cf164395e65066a1132bb36b7896)當成檔名
  • (3)這些物件的實體目錄與檔案也都會放在 .git\objects 目錄下,如下圖示:
 
 
 
 

(二)物件類型

[ 參考影片 ] (必看)
 
[ 物件的壓縮 ]  zlib 演算法
  • 提升存取效率。
  • 節省空間 : 計算出 blob 之間的差異,將這些差異儲存在一個名為 packfile 的檔案中。
  • (通常 packfile 會置於 .git\objects\pack 目錄)
  •  
 
[ 物件之間的關聯 ]
  • 透過 tree 物件 (資料夾的快照) 與 commit 物件 (每一個版本的快照) ,能夠得知 blob 與版本的關係。
  • 1.  blob 物件:檔案的"內容"。
  • 工作目錄中某個檔案的 "內容"(當你執行 git add 指令的同時,這些新增檔案的內容就會立刻被寫入成為 blob 物件,檔名則是物件內容的雜湊運算結果)。
 
  • 2.  tree 物件:儲存目錄下的資訊。
  • 包含該目錄下的檔名、對應的 blob 物件名稱、檔案連結(symbolic link) 或其他 tree 物件等等。
  • tree 物件可以包含其他 tree 物件,像「資料夾」。
  • tree 物件是在特定版本下某個資料夾的快照(Snapshot)。
 
  • 3.  commit 物件:記錄 tree 物件和版本資訊。
  • 一個 commit 物件代表著 Git 的一次提交,記錄著特定提交版本有哪些 tree 物件、版本提交時間、記錄訊息。
  • 記錄上一層的 commit 物件名稱 (只有第一次 commit 的版本沒有上層 commit 物件名稱)。
 
  • 4.  tag 物件:
  • 用來關聯 commit 物件 (也可以關聯到特定 blob、tree 物件)
  • 儲存額外的參考資訊(metadata),例如: tag 名稱。
  • [ 用途 ]  替 commit 物件標示一個易懂的名稱,通常代表某個特定發行的版本,或是特殊意義的版本。
 
 
 
 

(三)物件結構的優點

1.  有效率的處理大型專案
  • 所有 blob 物件都是透過「內容」來做定址的 (content addressable),可以提高不同版本之間搜尋內容的效率。
 
 
2.  保護歷史紀錄
  • [ 多層關聯保護 ]  增加竄改難度 ( commit >> tree >> blob、tree ... )
  • 每次提交變更都會產生一個 commit 物件,commit 物件的名稱是透過 commit 物件的內容產生。
  • commit 物件會關連到 tree 物件,tree 物件的名稱又是透過 tree 物件的內容所產生。
  • tree 物件又會關聯到 blob 與 tree 物件,這些物件的名稱也是透過內容產生。
 
  • 由於 Git 儲存庫經常會被 clone 或 fork,只要是被 clone 過的儲存庫,來源的儲存庫只要任何一個物件被修改,這些 clone 出去的儲存庫就很難再合併回來,所以幾乎不可能任意竄改版本紀錄。
 
 
3.  定期封裝物件
  • [ 建立新物件 ]
  • 在 Git 中的 "物件" 代表版本庫中的檔案。而在版本異動的過程中,專案中的程式碼或其他檔案會被更新,每次更新時,只要檔案內容不一樣,就會建立新的 "物件",這些不同內容的檔案全部都會保留下來。
 
  • [ 製作封裝檔 ]
  • Git 的設計可以將老舊的 "物件" 自動封裝進一個封裝檔(packfile)中,以改善檔案存取效率。
  • 新增的檔案會以單一檔案的方式存在著,也代表一個 Git 版本庫中的 "檔案" 就是一個 Git "物件",但每隔一段時間就會需要重新封裝(repacking)。
  • 執行重新封裝 : git gc
  • 檢查 Git 維護檔案系統是否完整 : git fsck