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-9
和 a-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 工作流程如下:
- 在工作目錄中修改檔。
- 暫存檔,將檔的快照放入暫存區域。
- 提交更新,找到暫存區域的檔,將快照永久性存儲到 Git 倉庫目錄。
如果 Git 目錄中保存著的特定版本檔,就屬於已提交狀態。 如果作了修改並已放入暫存區域,就屬於已暫存狀態。 如果自上次取出後,作了修改但還沒有放到暫存區域,就是已修改狀態。 在Git 基礎一章,你會進一步瞭解這些狀態的細節,並學會如何根據檔狀態實施後續操作,以及怎樣跳過暫存直接提交。