Git基礎和原理


Git 究竟是怎樣的一個系統呢? 請注意接下來的內容非常重要,若你理解了 Git 的思想和基本工作原理,用起來就會知其所以然,遊刃有餘。 在開始學習 Git 的時候,請努力分清你對其它版本管理系統的已有認識,如 Subversion 和 Perforce 等;這麼做能幫助你使用工具時避免發生混淆。 Git 在儲存和對待各種資訊的時候與其它版本控制系統有很大差異,儘管操作起來的命令形式非常相近,理解這些差異將有助於防止你使用中的困惑。

直接記錄快照,而非差異比較

Git 和其它版本控制系統(包括 Subversion 和近似工具)的主要差別在於 Git 對待資料的方法。 概念上來區分,其它大部分系統以檔案變更列表的方式儲存資訊。 這類系統(CVS、Subversion、Perforce、Bazaar 等等)將它們儲存的資訊看作是一組基本檔案和每個檔案隨時間逐步累積的差異。儲存每個檔案與初始版本的差異,如下圖所示 -

Git 不按照以上方式對待或儲存資料。 反之,Git 更像是把資料看作是對小型檔案系統的一組快照。 每次你提交更新,或在 Git 中儲存專案狀態時,它主要對當時的全部檔案製作一個快照並儲存這個快照的索引。 為了高效,如果檔案沒有修改,Git 不再重新儲存該檔案,而是只保留一個連結指向之前儲存的檔案。 Git 對待資料更像是一個 快照流。如下圖所示 -

這是 Git 與幾乎所有其它版本控制系統的重要區別。 因此 Git 重新考慮了以前每一代版本控制系統延續下來的諸多方面。 Git 更像是一個小型的檔案系統,提供了許多以此為基礎構建的超強工具,而不只是一個簡單的 VCS。 稍後我們在 Git 分支討論 Git 分支管理時,將探究這種方式對待資料所能獲得的益處。

近乎所有操作都是本地執行

在 Git 中的絕大多數操作都只需要存取本地檔案和資源,一般不需要來自網路上其它計算機的資訊。 如果你習慣於所有操作都有網路延時開銷的集中式版本控制系統,Git 在這方面會讓你感到速度之神賜給了 Git 超凡的能量。 因為你在本地磁碟上就有專案的完整歷史,所以大部分操作看起來瞬間完成。

舉個例子,要瀏覽專案的歷史,Git 不需外連到伺服器去獲取歷史,然後再顯示出來——它只需直接從本地資料庫中讀取。 你能立即看到專案歷史。 如果想檢視當前版本與一個月前的版本之間引入的修改,Git 會查詢到一個月前的檔案做一次原生的差異計算,而不是由遠端伺服器處理或從遠端伺服器拉回舊版本檔案再來本地處理。

這也意味著你離線或者沒有 VPN 時,幾乎可以進行任何操作。 如你在飛機或火車上想做些工作,你能愉快地提交,直到有網路連線時再上傳。 如你回家後 VPN 用戶端不正常,你仍能工作。 使用其它系統,做到如此是不可能或很費力的。 比如,用 Perforce,你沒有連線伺服器時幾乎不能做什麼事;用 Subversion 和 CVS,你能修改檔案,但不能向資料庫提交修改(因為你的本地資料庫離線了)。 這看起來不是大問題,但是你可能會驚喜地發現它帶來的巨大的不同。

Git 保證完整性

Git 中所有資料在儲存前都計算校驗和,然後以校驗和來參照。 這意味著不可能在 Git 不知情時更改任何檔案內容或目錄內容。 這個功能建構在 Git 底層,是構成 Git 哲學不可或缺的部分。 若你在傳送過程中丟失資訊或損壞檔案,Git 就能發現。

Git 用以計算校驗和的機制叫做 SHA-1 雜湊(hash,雜湊)。 這是一個由 40 個十六進位制字元(0-9a-f)組成字串,基於 Git 中檔案的內容或目錄結構計算出來。 SHA-1 雜湊看起來是這樣:

24b9da6552252987aa493b52f8696cd6d3b0037

Git 中使用這種雜湊值的情況很多,你將經常看到這種雜湊值。 實際上,Git 資料庫中儲存的資訊都是以檔案內容的雜湊值來索引,而不是檔案名。

Git 一般只新增資料

你執行的 Git 操作,幾乎只往 Git 資料庫中增加資料。 很難讓 Git 執行任何不可逆操作,或者讓它以任何方式清除資料。 同別的 VCS 一樣,未提交更新時有可能丟失或弄亂修改的內容;但是一旦你提交快照到 Git 中,就難以再丟失資料,特別是如果你定期的推播資料庫到其它倉庫的話。

這使得我們使用 Git 成為一個安心愉悅的過程,因為我們深知可以盡情做各種嘗試,而沒有把事情弄糟的危險。 更深度探討 Git 如何儲存資料及恢復丟失資料的話題,請參考撤消操作。

三種狀態

請注意!如果你希望後面的學習更順利,記住下面這些關於 Git 的概念。 Git 有三種狀態,你的檔案可能處於其中之一:已提交(committed)、已修改(modified)和已暫存(staged)。 已提交表示資料已經安全的儲存在本地資料庫中。 已修改表示修改了檔案,但還沒儲存到資料庫中。 已暫存表示對一個已修改檔案的當前版本做了標記,使之包含在下次提交的快照中。

由此引入 Git 專案的三個工作區域的概念:Git 倉庫、工作目錄以及暫存區域。工作目錄、暫存區域以及 Git 倉庫如下圖所示 -

Git 倉庫目錄是 Git 用來儲存專案的後設資料和物件資料庫的地方。 這是 Git 中最重要的部分,從其它計算機克隆倉庫時,拷貝的就是這裡的資料。

工作目錄是對專案的某個版本獨立提取出來的內容。 這些從 Git 倉庫的壓縮資料庫中提取出來的檔案,放在磁碟上供你使用或修改。

暫存區域是一個檔案,儲存了下次將提交的檔案列表資訊,一般在 Git 倉庫目錄中。 有時候也被稱作‘索引’,不過一般說法還是叫暫存區域。

基本的 Git 工作流程如下:

  1. 在工作目錄中修改檔案。
  2. 暫存檔案,將檔案的快照放入暫存區域。
  3. 提交更新,找到暫存區域的檔案,將快照永久性儲存到 Git 倉庫目錄。

如果 Git 目錄中儲存著的特定版本檔案,就屬於已提交狀態。 如果作了修改並已放入暫存區域,就屬於已暫存狀態。 如果自上次取出後,作了修改但還沒有放到暫存區域,就是已修改狀態。 在Git 基礎一章,你會進一步了解這些狀態的細節,並學會如何根據檔案狀態實施後續操作,以及怎樣跳過暫存直接提交。