Git 究竟是怎樣的一個系統(tǒng)呢? 請注意接下來的內(nèi)容非常重要,若你理解了 Git 的思想和基本工作原理,用起來就會知其所以然,游刃有余。 在開始學(xué)習(xí) Git 的時候,請努力分清你對其它版本管理系統(tǒng)的已有認(rèn)識,如 Subversion 和 Perforce 等;這么做能幫助你使用工具時避免發(fā)生混淆。 Git 在保存和對待各種信息的時候與其它版本控制系統(tǒng)有很大差異,盡管操作起來的命令形式非常相近,理解這些差異將有助于防止你使用中的困惑。
Git 和其它版本控制系統(tǒng)(包括 Subversion 和近似工具)的主要差別在于 Git 對待數(shù)據(jù)的方法。 概念上來區(qū)分,其它大部分系統(tǒng)以文件變更列表的方式存儲信息。 這類系統(tǒng)(CVS、Subversion、Perforce、Bazaar 等等)將它們保存的信息看作是一組基本文件和每個文件隨時間逐步累積的差異。存儲每個文件與初始版本的差異,如下圖所示:
Git 不按照以上方式對待或保存數(shù)據(jù)。 反之,Git 更像是把數(shù)據(jù)看作是對小型文件系統(tǒng)的一組快照。 每次你提交更新,或在 Git 中保存項(xiàng)目狀態(tài)時,它主要對當(dāng)時的全部文件制作一個快照并保存這個快照的索引。 為了高效,如果文件沒有修改,Git 不再重新存儲該文件,而是只保留一個鏈接指向之前存儲的文件。 Git 對待數(shù)據(jù)更像是一個 快照流。如下圖所示:
這是 Git 與幾乎所有其它版本控制系統(tǒng)的重要區(qū)別。 因此 Git 重新考慮了以前每一代版本控制系統(tǒng)延續(xù)下來的諸多方面。 Git 更像是一個小型的文件系統(tǒng),提供了許多以此為基礎(chǔ)構(gòu)建的超強(qiáng)工具,而不只是一個簡單的 VCS。 稍后我們在 Git 分支討論 Git 分支管理時,將探究這種方式對待數(shù)據(jù)所能獲得的益處。
在 Git 中的絕大多數(shù)操作都只需要訪問本地文件和資源,一般不需要來自網(wǎng)絡(luò)上其它計(jì)算機(jī)的信息。 如果你習(xí)慣于所有操作都有網(wǎng)絡(luò)延時開銷的集中式版本控制系統(tǒng),Git 在這方面會讓你感到速度之神賜給了 Git 超凡的能量。 因?yàn)槟阍诒镜卮疟P上就有項(xiàng)目的完整歷史,所以大部分操作看起來瞬間完成。
舉個例子,要瀏覽項(xiàng)目的歷史,Git 不需外連到服務(wù)器去獲取歷史,然后再顯示出來——它只需直接從本地?cái)?shù)據(jù)庫中讀取。 你能立即看到項(xiàng)目歷史。 如果想查看當(dāng)前版本與一個月前的版本之間引入的修改,Git 會查找到一個月前的文件做一次本地的差異計(jì)算,而不是由遠(yuǎn)程服務(wù)器處理或從遠(yuǎn)程服務(wù)器拉回舊版本文件再來本地處理。
這也意味著你離線或者沒有 VPN 時,幾乎可以進(jìn)行任何操作。 如你在飛機(jī)或火車上想做些工作,你能愉快地提交,直到有網(wǎng)絡(luò)連接時再上傳。 如你回家后 VPN 客戶端不正常,你仍能工作。 使用其它系統(tǒng),做到如此是不可能或很費(fèi)力的。 比如,用 Perforce,你沒有連接服務(wù)器時幾乎不能做什么事;用 Subversion 和 CVS,你能修改文件,但不能向數(shù)據(jù)庫提交修改(因?yàn)槟愕谋镜財(cái)?shù)據(jù)庫離線了)。 這看起來不是大問題,但是你可能會驚喜地發(fā)現(xiàn)它帶來的巨大的不同。
Git 中所有數(shù)據(jù)在存儲前都計(jì)算校驗(yàn)和,然后以校驗(yàn)和來引用。 這意味著不可能在 Git 不知情時更改任何文件內(nèi)容或目錄內(nèi)容。 這個功能建構(gòu)在 Git 底層,是構(gòu)成 Git 哲學(xué)不可或缺的部分。 若你在傳送過程中丟失信息或損壞文件,Git 就能發(fā)現(xiàn)。
Git 用以計(jì)算校驗(yàn)和的機(jī)制叫做 SHA-1 散列(hash,哈希)。 這是一個由 40 個十六進(jìn)制字符(0-9 和 a-f)組成字符串,基于 Git 中文件的內(nèi)容或目錄結(jié)構(gòu)計(jì)算出來。 SHA-1 哈希看起來是這樣:
24b9da6552252987aa493b52f8696cd6d3b0037
Git 中使用這種哈希值的情況很多,你將經(jīng)常看到這種哈希值。 實(shí)際上,Git 數(shù)據(jù)庫中保存的信息都是以文件內(nèi)容的哈希值來索引,而不是文件名。
你執(zhí)行的 Git 操作,幾乎只往 Git 數(shù)據(jù)庫中增加數(shù)據(jù)。 很難讓 Git 執(zhí)行任何不可逆操作,或者讓它以任何方式清除數(shù)據(jù)。 同別的 VCS 一樣,未提交更新時有可能丟失或弄亂修改的內(nèi)容;但是一旦你提交快照到 Git 中,就難以再丟失數(shù)據(jù),特別是如果你定期的推送數(shù)據(jù)庫到其它倉庫的話。
這使得我們使用 Git 成為一個安心愉悅的過程,因?yàn)槲覀兩钪梢员M情做各種嘗試,而沒有把事情弄糟的危險(xiǎn)。 更深度探討 Git 如何保存數(shù)據(jù)及恢復(fù)丟失數(shù)據(jù)的話題,請參考撤消操作。
請注意!如果你希望后面的學(xué)習(xí)更順利,記住下面這些關(guān)于 Git 的概念。 Git 有三種狀態(tài),你的文件可能處于其中之一:已提交(committed)、已修改(modified)和已暫存(staged)。 已提交表示數(shù)據(jù)已經(jīng)安全的保存在本地?cái)?shù)據(jù)庫中。 已修改表示修改了文件,但還沒保存到數(shù)據(jù)庫中。 已暫存表示對一個已修改文件的當(dāng)前版本做了標(biāo)記,使之包含在下次提交的快照中。
由此引入 Git 項(xiàng)目的三個工作區(qū)域的概念:Git 倉庫、工作目錄以及暫存區(qū)域。工作目錄、暫存區(qū)域以及 Git 倉庫如下圖所示:
Git 倉庫目錄是 Git 用來保存項(xiàng)目的元數(shù)據(jù)和對象數(shù)據(jù)庫的地方。 這是 Git 中最重要的部分,從其它計(jì)算機(jī)克隆倉庫時,拷貝的就是這里的數(shù)據(jù)。
工作目錄是對項(xiàng)目的某個版本獨(dú)立提取出來的內(nèi)容。 這些從 Git 倉庫的壓縮數(shù)據(jù)庫中提取出來的文件,放在磁盤上供你使用或修改。
暫存區(qū)域是一個文件,保存了下次將提交的文件列表信息,一般在 Git 倉庫目錄中。 有時候也被稱作‘索引’,不過一般說法還是叫暫存區(qū)域。
基本的 Git 工作流程如下:
⒈ 在工作目錄中修改文件。
⒉ 暫存文件,將文件的快照放入暫存區(qū)域。
⒊ 提交更新,找到暫存區(qū)域的文件,將快照永久性存儲到 Git 倉庫目錄。
如果 Git 目錄中保存著的特定版本文件,就屬于已提交狀態(tài)。 如果作了修改并已放入暫存區(qū)域,就屬于已暫存狀態(tài)。 如果自上次取出后,作了修改但還沒有放到暫存區(qū)域,就是已修改狀態(tài)。 在Git 基礎(chǔ)一章,你會進(jìn)一步了解這些狀態(tài)的細(xì)節(jié),并學(xué)會如何根據(jù)文件狀態(tài)實(shí)施后續(xù)操作,以及怎樣跳過暫存直接提交。