Git——Git基本概念進階介紹(四)

Git——Git基本概念進階介紹(四)

 

我們在上一篇文章中已經介紹了Git的一個典型應用,但我們忽略了其中的某些問題與Git的內部機制。下面就在介紹一些Git實現中的基本概念,它主要來自於《Git版本控制管理》第四章節。意料之中的,掌握典型使用總是比掌握設計原理簡單的多~~~

1.版本庫

Git版本庫(repository)只是一個簡單的數據庫,其中包含所有用來維護與管理項目的修訂版本和歷史的信息。在Git中,跟大多數VCS一樣,一個版本庫維護項目整個生命週期的完整副本。然而,Git不僅提供版本庫中所有文件的完整副本,還提供版本庫本身的副本。

Git在每個版本庫裏維護一組配置值,如之前設置的版本庫的用戶名和email地址等。不像文件數據和其他版本庫的元數據,在把一個版本庫clone或者複製到另一個版本庫的時候配置信息是不跟着轉移的。相反,Git對每個網站、每個用戶、和每個版本的配置和設置信息都進行管理和檢查。

在版本庫中,Git維護兩個主要的數據結構:對象庫(Object store)和索引(index)。所有這些版本庫數據放在工作目錄根目錄下的名爲.git的隱藏子目錄中。

2.Git對象類型

對象庫是Git版本庫實現的心臟。它包含你的原始數據文件和所有日誌消息、作者信息、日期,以及其他用來重建項目任意版本或分支的信息。

Git放在對象庫裏的對象只有4種類型:塊(blob)、目錄樹(tree)、提交(commit)和標籤(tag)。這4種原子對象構成Git高層數據結構的基礎。

塊(blob)

文件的每一個版本表示爲一個塊。blob是“binary large object”的縮寫,是計算機領域的常用語,用來指代某些可以包含任意數據的變量或文件,同時其內部結構會被程序忽略。一個blob被視爲一個黑盒。一個blob保存一個文件的數據,但不包含任何關於這個文件的元數據,甚至連文件名也沒有

目錄樹(tree)

一個目錄樹對象代表一層目錄信息。它記錄blob標識符、路徑名和在一個目錄裏所有文件的一些元數據。它可以遞歸引用其他目錄書或子樹對象,從而建立一個包含文件和子目錄的完整層次結構。

提交(commit)

一個提交對象保存版本庫中每一次變化的元數據,包括作者、提交者、提交日期和日誌消息。每一個提交對象指向一個目錄樹對象,這個目錄樹對象在一張完整的快照中捕獲提交時版本庫的狀態。最初的提交或者根提交是沒有父提交的。大多數提交都有一個父提交,但也存在例外。

標籤(tag)

一個標籤對象分配一個任意的且人類可讀的名字給一個特定對象,通常是一個提交對象。雖然85c1c0a43f18923fe32ceb57d55116d42c04d496指的是一個確切且定義好的提交,但是一個更熟悉的標籤名(如Ver-1.0)可能會更有意義。

隨着時間的推移,所有信息在對象庫中會變化和增長,項目的編輯、添加和刪除都會被跟蹤和建模。爲了有效利用磁盤空間和網絡寬帶,Git把對象壓縮並存儲在打包文件(pack file)中,這些文件也在對象庫裏。

3.索引

索引是一個臨時的、動態的二進制文件,它描述整個版本庫的目錄結構。更具體的說,索引捕獲項目在某個時刻的整體結構的一個版本。項目的狀態可以用一個提交和一顆目錄樹表示,它可以來自項目歷史中的任意時刻,或者它可以是你正在開發的未來狀態。

Git的關鍵特色之一就是它允許你用有條理的、定義好的步驟來改變索引的內容。索引使得開發的推進與提交的變更能夠分離開來。

下面是它的工作原理。作爲開發人員,你通過執行Git命令在索引中暫存(stage)變更。變更通常是添加、刪除或者編輯某個文件或某些文件。索引會記錄和保存那些變更,保障它們的安全直到你準備好提交了。還可以刪除或替換索引中的變更。因此,索引支持一個由你主導的從複雜的版本庫狀態到一個可推測的更好狀態的逐步過渡。

4.可尋址內容名稱

Gi對象庫被組織及實現成一個內容尋址的存儲系統。具體而言,對象庫中的每個對象都有一個唯一的名稱,這個名稱是向對象的內容使用SHA1得到的SHA1散列值。因爲一個對象的完整內容決定了這個散列值,並且認爲這個散列值能有效 並唯一地對應特定的內容,所以SHA1散列值用來做對象數據庫中對象的名字和索引是完全充分的。文件的任何微小變化都會導致SHA1散列值的改變,使得文件的新版本被單獨編入索引。

SHA1的值是一個160位的數,通常表示爲一個40位的十六進制數,比如85c1c0a43f18923fe32ceb57d55116d42c04d496。有時候 ,在顯示期間,SHA1值被簡化成一個較小的、唯一的前綴。Git用戶所說的SHA1、散列碼和對象ID都是指同一個東西。

PS:SHA1散列計算的一個重要特性是不管內容在哪裏,它對同樣的內容始終產生同樣的ID。換言之,在不同目錄甚至不同機器中的相同文件內容產生的SHA1哈希ID是完全相同的。因此,文件的SHA1散列ID是一種有效的全局唯一標識符。這裏有一個強大的推論,在互聯網上,文件或者任意大小的blob都可以通過比較它們的SHA1標識符來判斷是否相同。

5.Git追蹤內容

Git除了是VCS,同時還是一個內容追蹤系統。Git的內容追蹤主要表現爲兩種關鍵的方式。

首先,Git的對象庫基於其對象內容的散列計算的值,而不是基於用戶原始文件佈局的文件名或目錄名設置。因此,當Git放置一個文件到對象庫中的時候,它基於數據的散列值而不是文件名。事實上,Git並不追蹤那些與文件次相關的文件名或目錄名。再次強調,Git追蹤的是內容而不是文件。

如果兩個文件的內容完全一樣,無論是否在相同的目錄,Git在對象庫裏只保存一份blob形式的內容副本。如果文件有相同的SHA1值,它們的內容就是相同的。

如果這些文件中的一個發生了變化,Git會爲它重新計算一個新的SHA1值,識別出它現在是一個不同的blob對象,然後把這個心的blob對象加到對象庫裏。原來的blob在對象庫裏保持不變,爲沒有變化的文件所使用。

其次,當文件從一個版本到下一個版本的時候,Git的內容數據庫有效地存儲每個文件的每個版本,而不是它們的差異。因爲Git使用一個文件的全部內容的散列值作爲文件名,所以它必須對每個文件的完整副本進行操作。Git不能將工作或者對象庫條目建立在文件內容的一部分或者文件的兩個版本之間的差異上。

6.路徑名與內容

Git需要維護一個明確的文件列表來組成版本庫的內容。然而,這個需求並不需要Git的列表基於文件名。實際上,Git把文件名視爲一段區別於文件內容的數據。文件名和目錄名來自底層的文件系統,但是Git並不真正關心這些名字。Git僅僅記錄每個路徑名,並且確保通過它的內容精確地重建文件和目錄,這些都是由散列值來索引的。

7.打包文件

Git使用了一種叫做打包文件(pack file)的高效的存儲機制。要創建一個打包文件,Git首先定位內容非常相似的全部文件,然後爲它們之一存儲整個內容。之後計算相似文件之間的差異並且只保存差異。例如,如果你只是更改或添加文件中的一行,Git可能會存儲新版本的全部內容,然後記錄那一行更改作爲差異,並儲存在包裏。

存儲一個文件的整個版本用來構造其他版本的相似文件的差異是一個被廣泛使用的伎倆了。然而,Git文件打包的 非常巧妙。因爲Git是內容驅動的,所以它並不真正關心它計算出來的兩個文件之間的差異是否屬於同一個文件的兩個版本。這就是說,Git可以在版本庫裏的任何地方取出兩個文件的差異,只要它認爲它們足夠相似來產生良好的數據壓縮。因此,Git有一套相當複雜的算法來定位和匹配版本庫中潛在的全局候選差異。此外,Git可構造一些列差異文件,從一個文件的一個版本到第二個、第三個,等等。Git還維護打包文件表示每個完整文件(包括完整內容的文件和通過差異重建出來的文件)的原始blob的SHA1值。這給定位包內對象的索引機制提供了基礎。打包文件跟對象庫中其他對象存儲在一起。它們也用於網絡中版本庫的高效數據傳輸。

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章