1. 程式人生 > >git 使用詳解 (1)——歷史

git 使用詳解 (1)——歷史

服務 編輯 元數據 原始的 事先 史記 依然 sub 本地磁盤

版本控制系統(VCS)

有了它你就可以將某個文件回溯到之前的狀態,甚至將整個項目都回退到過去某個時間點的狀態。你可以比較文件的變化細節,查出最後是誰修改了哪個地方,從而導致出現怪異問題,又是誰在何時報告了某個功能缺陷等等。使用版本控制系統通常還意味著,就算你亂來一氣把整個項目中的文件改的改刪的刪,你也照樣可以輕松恢復到原先的樣子。但額外增加的工作量卻微乎其微。

集中化的版本控制系統

如何讓在不同系統上的開發者協同工作?於是,集中化的版本控制系統( Centralized Version Control Systems,簡稱 CVCS )應運而生。這類系統,諸如 CVS,Subversion 以及 Perforce 等,都有一個單一的集中管理的服務器,保存所有文件的修訂版本,而協同工作的人們都通過客戶端連到這臺服務器,取出最新的文件或者提交更新。多年以來,這已成為版本控制系統的標準做法。

現在,每個人都可以在一定程度上看到項目中的其他人正在做些什麽。而管理員也可以輕松掌控每個開發者的權限,並且管理一個 CVCS 要遠比在各個客戶端上維護本地數據庫來得輕松容易。

事分兩面,有好有壞。這麽做最顯而易見的缺點是中央服務器的單點故障

  • 如果宕機一小時,那麽在這一小時內,誰都無法提交更新,也就無法協同工作。
  • 要是中央服務器的磁盤發生故障,碰巧沒做備份,或者備份不夠及時,就還是會有丟失數據的風險。
  • 最壞的情況是徹底丟失整個項目的所有歷史更改記錄,而被客戶端提取出來的某些快照數據除外,但這樣的話依然是個問題,你不能保證所有的數據都已經有人事先完整提取出來過。
    本地版本控制系統也存在類似問題,只要整個項目的歷史記錄被保存在單一位置,就有丟失所有歷史更新記錄的風險。

分布式版本控制系統

於是分布式版本控制系統( Distributed Version Control System,簡稱 DVCS )面世了。在這類系統中,像 Git 等,客戶端並不只提取最新版本的文件快照,而是把原始的代碼倉庫 完整地 鏡像下來。這麽一來,任何一處協同工作用的服務器發生故障,事後都可以用任何一個鏡像出來的本地倉庫恢復。因為每一次的提取操作,實際上都是一次對代碼倉庫的完整備份
更進一步,許多這類系統都可以指定和若幹不同的遠端代碼倉庫進行交互。籍此,你就可以在同一個項目中,分別和不同工作小組的人相互協作。你可以根據需要設定不同的協作流程,比如層次模型式的工作流,而這在以前的集中式系統中是無法實現的。

Git 基礎

Git 究竟是怎樣的一個系統呢?若是理解了 Git 的思想和基本工作原理,用起來就會知其所以然,遊刃有余。在開始學習 Git 的時候,請不要嘗試把各種概念和其他版本控制系統(諸如 Subversion 和 Perforce 等)相比擬,否則容易混淆每個操作的實際意義。

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

Git 和其他版本控制系統的主要差別在於,Git 只關心文件數據的整體是否發生變化,而大多數其他系統則只關心 文件內容的具體差異。這類系統(CVS,Subversion,Perforce,Bazaar 等等)每次記錄有哪些文件作了更新,以及都更新了哪些行的什麽內容。

Git 並 不保存 這些前後變化的差異數據。實際上,Git 更像是把變化的文件作快照後,記錄在一個微型的文件系統中。每次提交更新時,它會縱覽一遍所有文件的指紋信息並對文件作一快照,然後保存一個指向這次快照的索引。為提高性能,若文件沒有變化,Git 不會再次保存,而只對上次保存的快照作一鏈接。

這是 Git 同其他系統的重要區別。Git 更像是個小型的文件系統,但它同時還提供了許多以此為基礎的超強工具,而不只是一個簡單的 VCS。

在 Git 中的絕大多數操作都只需要訪問本地文件和資源,不用連網。但如果用 CVCS 的話,差不多所有操作都需要連接網絡。因為 Git 在本地磁盤上就保存著所有當前項目的歷史更新,所以處理起來速度飛快。

時刻保持數據完整性

Git 使用 SHA-1 算法計算數據的校驗和,通過對文件的內容或目錄的結構計算出一個 SHA-1 哈希值,作為指紋字符串。該字串由 40 個十六進制字符(0-9 及 a-f)組成,看起來就像是:
24b9da6552252987aa493b52f8696cd6d3b00373
Git 的工作完全依賴於這類指紋字串,所以你會經常看到這樣的哈希值。實際上,所有保存在 Git 數據庫中的東西都是用此哈希值來作索引的,而不是靠文件名。

多數操作僅添加數據

常用的 Git 操作大多僅僅是把數據添加到數據庫。因為任何一種不可逆的操作,比如刪除數據,都會使回退或重現歷史版本變得困難重重。

但在 Git 裏,一旦提交快照之後就完全不用擔心丟失數據,特別是養成定期推送到其他倉庫的習慣的話。

文件的三種狀態

對於任何一個文件,在 Git 內都只有三種狀態:已提交(committed)已修改(modified)已暫存(staged)。已提交表示該文件已經被安全地保存在本地數據庫中了;已修改表示修改了某個文件,但還沒有提交保存;已暫存表示把已修改的文件放在下次提交時要保存的清單中。

由此我們看到 Git 管理項目時,文件流轉的三個工作區域:Git 的工作目錄暫存區域,以及本地倉庫

每個項目都有一個 Git 目錄(譯註:如果 git clone 出來的話,就是其中 .git 的目錄;如果git clone --bare的話,新建的目錄本身就是 Git 目錄。),它是 Git 用來保存元數據和對象數據庫的地方。該目錄非常重要,每次克隆鏡像倉庫的時候,實際拷貝的就是這個目錄裏面的數據。

從項目中取出某個版本的所有文件和目錄,用以開始後續工作的叫做工作目錄。這些文件實際上都是從 Git 目錄中的壓縮對象數據庫中提取出來的,接下來就可以在工作目錄中對這些文件進行編輯。

所謂的暫存區域只不過是個簡單的文件,一般都放在 Git 目錄中。有時候人們會把這個文件叫做索引文件,不過標準說法還是叫暫存區域。

基本的 Git 工作流程如下:

  1. 在工作目錄中修改某些文件。
  2. 對修改後的文件進行快照,然後保存到暫存區域。
  3. 提交更新,將保存在 暫存區域 的文件快照永久轉儲到 Git 目錄 中。

所以,我們可以從文件所處的位置來判斷狀態:如果是 Git 目錄中保存著的特定版本文件,就屬於已提交狀態;如果作了修改並已放入暫存區域,就屬於已暫存狀態;如果自上次取出後,作了修改但還沒有放到暫存區域,就是已修改狀態。

git 使用詳解 (1)——歷史