Skip to main content

Git 能幫我什麼

記錄檔案快照,而不是差異

Git 與其它版本控制系統(包含 Subversion 以及與它相關的)最主要的差別是如何處理資料的方式。 一般來說,其他大部分的系統是紀錄一連串檔案更改的資訊。 這些系統(CVS、Subversion、Perforce、Bazaar…等等)儲存一組基本的檔案以及這些檔案隨時間遞增的更動資料。

!https://git-scm.com/book/en/v2/images/deltas.png

但是 Git 不是用這種方式儲存及看待這些資料, 而是將其視為小型檔案系統的一組快照(Snapshot)。 每當你提交(commit)(註:在 Git 儲存目前專案的狀態)時,Git 會紀錄下你所有目前檔案的樣子,並且參照到這次快照中。 為了講求效率,只要檔案沒有變更,Git 不會再度儲存該檔案,而是直接將上一次相同的檔案參照到這次快照中。 Git 把它的資料視為一連串的快照。

!https://git-scm.com/book/en/v2/images/snapshots.png

這是 Git 和其他相似的版本管理系統之間一個重要的差異。 它使得 Git 從各方面重新考量被其他老一輩版本管理系統所採用的作法, 並使得 Git 更像是一個上面有一些強大工具的小型檔案系統,而不僅只是版本管理系統。 本書將會在 [ch03-git-branching] 裡面介紹 Git 分支時,帶領你探索採用這種做法所獲得的好處。

大部份的操作皆可在本地端完成

大部份 Git 的操作皆只需要本地端的檔案及資源即可完成 — 通常並不需要網路上其它電腦的資訊。 如果你以前使用過每項操作都需要網路延遲的集中式版本控制系統,在這方面 Git 將會讓你覺得速度快到有如神助。 因為專案所有的歷史資料都存在你的本機磁碟中,大多數的操作看起來都像是瞬間完成的。

例如:想要瀏覽專案的歷史時,Git 不需要到伺服器下載歷史再顯示 — 就只需要從本機的資料庫讀取。 這意味著你幾乎馬上就可以看到專案的歷史。 若讀者想瞭解某個檔案一個月前的版本與現在版本的差別,Git 可以找出一個月前的檔案並在本機比對差異,而不是要求遠端的伺服器執行這項工作,或者從伺服器取回舊版本的檔案之後才在本機比對。

這也代表你只有一點點操作沒辦法在你斷線或是中斷 VPN 後執行。 如果你在飛機或火車上想要做些小工作,你可以愉快的提交並且等到連上網路後再上傳。 如果你回家後沒辦法使 VPN 正常運作,你仍然可以進行你的工作。 在很多其他的系統上,這麼做通常是不可能或是非常痛苦的事。 以 Perforce 為例,當你連不上伺服器時,你幾乎沒事可做。在 Subversion 和 CVS 中,你可以修改檔案,但是你沒辦法提交版本(只因為你連不上資料庫)。 這看起來可能不是什麼大問題,但是你可能會驚訝於 Git 能做到的事情有這麼大的差異。

Git 能檢查完整性

在 Git 中所有的物件在儲存前都會被計算校驗碼(checksum)並以校驗碼參照物件。 這意味著你不可能瞞著 Git 對任何檔案或目錄進行修改。 此功能內建在 Git 底層並整合到它的設計哲學。 Git 更能夠馬上察覺傳輸時的遺失或是檔案的毀損。

Git 用來計算校驗碼的機制稱為 SHA-1 雜湊演算法。 一個校驗碼是由 40 個 16 進位的字母(0–9 和 a–f)所組成,Git 會根據檔案的內容和資料夾的結構來計算。 一個 SHA-1 校驗碼看起來如下所示:

24b9da6552252987aa493b52f8696cd6d3b00373

你會 Git 中到處都看到校驗碼,因為校驗碼被 Git 到處使用。 事實上在 Git 的資料庫內,每個檔案都是用其內容的校驗碼來儲存,而不是使用檔名。

Git 通常只增加資料

當你使用 Git,幾乎所有的動作都只是增加資料到Git的資料庫。 你很難藉此讓做出讓系統無法復原或者清除資料的動作。 在任何版本控制系統中,你尚未提交的修改都有可能會遺失或者搞亂。 但是只要你提交快照到 Git 後,很難會發生遺失的情況,特別是你定期將資料庫推送(push)到其它儲存庫時,就更不可能會弄丟資料。

這讓我們在使用 Git 的時候時可以像在玩玩具一樣,因為我們知道我們可以隨意操作而不會弄壞任何東西。 在 復原 中,我們會進一步討論 Git 如何儲存資料,以及你如何復原看似遺失的資料。

三種狀態

現在,請特別注意。 若你希望接下來的學習過程順利些,請務必記住以下這些關於 Git 的知識。 Git 會把你的檔案標記為三種主要的狀態:已提交(committed)、已修改(modified)及已預存(staged)。 已提交代表這檔案己安全地存在你的本地端資料庫。 己修改代表這檔案已被修改但尚未提交到本地端資料庫。 已預存代表這檔案將會被存到下次你提交的快照中。

這帶領我們到 Git 專案的三個主要區域:Git 資料夾、工作目錄(working directory)以及預存區(staging area)。

!https://git-scm.com/book/en/v2/images/areas.png

Git 資料夾是 Git 用來儲存你專案的後設資料及物件資料庫的地方。 這是 Git 最重要的部份,而且當你克隆一個其他電腦的儲存庫時,這個資料夾也會被同時複製。

工作目錄是專案被檢出的某一個版本。 這些檔案從 Git 目錄內被壓縮過的資料庫中拉出來並放在硬碟供你使用或修改。

預存區是一個單一檔案,一般來說放在 Git 目錄下,儲存關於下次提交的資訊。 有時它會稱為索引「index」,但現在更常被稱呼為預存區。

基本 Git 工作流程大致如下:

  1. 你在你工作目錄修改檔案。
  2. 預存檔案,將檔案的快照新增到預存區。
  3. 做提交的動作,這會讓存在預存區的檔案快照永久地儲存在 Git 目錄中。

若檔案已被存於 Git 資料夾內,則稱為已提交。 若檔案先被修改,接著被增加到預存區域,則稱為已預存。 若檔案被檢出後有被修改,但未被預存,則稱為已修改。 在 [ch02-git-basics] 內你將會學到更多關於這些狀態的知識以及如何利用它們的優點或者直接略過預存步驟。

Git 常見專有名詞

  • 儲存庫 ( Repository ):Git 儲存庫是代碼庫,包含了所有的文件和歷史記錄,分為本地儲存庫和遠端儲存庫。
  • 本地儲存庫 ( Local Repository ):這是存儲在你本機上的 Git 儲存庫,用於開發和跟蹤你的代碼。
  • 遠端儲存庫 (Remote Repository):這是存儲在遠端程服務器 (gitlab 或 github..等)上的Git儲存庫,用於多人協作和代碼共享。
  • 提交 (Commit):提交是程式碼的一個快照,包含了你所做的變更。每次提交都有一個唯一的SHA-1 哈希值。
  • 分支 (Branch):分支是代碼開發的平行路線,在不影響主要代碼的情況下進行開發功能。
  • 主分支 (Master/Branch):這是主要的代碼分支,通常用於穩定的代碼版本。常用主分支的名稱是main。
  • 合併 (Merge):合併是將一個分支的變更合併到另一個分支,通常是將功能分支的變更合併到主分支。
  • Clone:Clone是從遠端儲存庫複製一份完整程式碼到本機儲存庫。
  • 拉 (Pull):Pull 是將遠程儲存庫的最新變更更新到你的本地儲存庫以保持同步。
  • 推 (Push):Push 是將你的本地變更上傳到遠程儲存庫。