== 入門 ==

我將用類比方式來介紹版本控制的概念。更嚴謹的解釋參見
http://en.wikipedia.org/wiki/Revision_control[維基百科版本修訂控制條目]。

=== 工作是玩 ===

我從小就玩電腦遊戲。相反，我只是在長大後才開始使用版本控制系統。我想我並不特
殊，並且，對比兩者工作方式可使這些概念更易解釋，也易於理解。

編寫代碼，或編輯文檔和玩遊戲差不多。在你做出了很多進展之後，你最好保存一下。
去做這個，會點擊你所信任的編輯器保存按鈕就好了。

但這將覆蓋老版本。就像那些學校裡玩的老遊戲，只有一個存檔：你確實可以保存，但
你不能回到更老的狀態了。這真讓人掃興，因為那個狀態可能恰好保存了這個遊戲特別
有意思一關，說不定哪天你想再玩一下呢。或者更糟糕的，你當前的保存是個必敗局，
這樣你就不得不從頭開始玩了。

=== 版本控制 ===

在編輯的時候，如果想保留舊版本，你可以將檔案“另存為”一個不同的檔案，或在保
存之前將檔案拷貝到別處。你可能壓縮這些檔案以節省空間。這是一個初級的靠手工的
版本控制方式。遊戲軟件早就提高了這塊，很多都提供多個基于時間戳的自動存檔槽。

讓我們看看稍稍複雜的情況。比如你有很多放在一起的檔案，比如項目源碼，或網站文
件。現在如你想保留舊版本，你不得不把整個目錄存檔。手工保存多個版本很不方便，
而且很快會耗費巨大。

在一些電腦遊戲裡，一個存檔真的包含在一個充滿檔案的目錄裡。這些遊戲為玩家屏蔽
了這些細節，並提供一個方便易用的界面來管理該目錄的不同版本。

版本控制系統也沒有兩樣。兩者提供友好的界面，來管理目錄裡的東西。你可以頻繁保
存，也可以之後加載任一保存。不像大多計算機遊戲，版本控制系統通常精於節省存儲
空間。一般情況如果兩個版本間只有少數檔案的變更，每個檔案的變更也不大，那就只
存儲差異的部分，而不是把全部拷貝的都保存下來，以節省存儲空間。

=== 分佈控制 ===

現在設想一個很難的遊戲。太難打了，以至于世界各地很多骨灰級玩家決定組隊，分享
他們遊戲存檔以攻克它。Speedrun們就是實際中的例子：在同一個遊戲裡，玩家們分別
攻克不同的等級，協同工作以創造驚人戰績。

你如何搭建一個系統，使得他們易於得到彼此的存檔？並易於上載新的存檔？

在過去，每個項目都使用中心式版本控制。某個伺服器上放所有保存的遊戲記錄。其他
人就不用了。每個玩家在他們機器上最多保留幾個遊戲記錄。當一個玩家想更新進度時
候，他們需要把最新進度從主伺服器下載下來，玩一會兒，保存並上載到主伺服器以供
其他人使用。

假如一個玩家由於某種原因，想得到一個較舊版本的遊戲進度怎麼樣？或許當前保存的
遊戲是一個注定的敗局，因為某人在第三級忘記撿某個物品；他們希望能找到最近一個
可以完成的遊戲記錄。或者他們想比較兩個舊版本間的差異，來估算某個特定玩家幹了
多少活。

查看舊版本的理由有很多，但檢查的辦法都是一樣的。他們必須去問中心伺服器要那個
舊版本的記錄。需要的舊版本越多，和伺服器的交互就越多。

新一代的版本控制系統，Git就是其中之一，是分散式的，可以被認作廣義上的中心式系
統。從主伺服器下載時玩家會得到所有保存的記錄，而不僅是最新版。這看起來他們好
像把中心伺服器做了個鏡像。

最初的克隆操作可能比較費時，特別當有很長歷史的時，但從長遠看這是值得的。一個
顯而易見的好處是，當查看一個舊版本時，不再需要和中心伺服器通訊了。

=== 一個誤區 ===

一個很常見的錯誤觀念是，分散式系統不適合需要官方中心倉庫的項目。這與事實並不
相符。給誰照相也不會偷走他們的靈魂。類似地，克隆主倉庫並不降低它的重要性。

一般來說，一個中心版本控制系統能做的任何事，一個良好設計的分散式系統都能做得
更好。網絡資源總要比本地資源耗費更費。不過我們應該在稍後分析分散式方案的缺點，
這樣人們才不會按照習慣做出錯誤的比較。

一個小項目或許只需要分散式系統提供的一小部分功能，但是，在項目很小的時候，應
該用規劃不好的系統？就好比說，在計算較小數目的時候應該使用羅馬數字？

而且，你的項目的增長可能會超出你最初的預期。從一開始就使用Git好似帶著一把瑞士
軍刀，儘管你很多時候只是用它來開開瓶蓋。某天你迫切需要一把改錐，你就會慶幸你
所有的不單單是一個啟瓶器。

=== 合併衝突 ===

對於這個話題，電腦遊戲的類比顯得不夠用。那讓我們再來看看文檔編輯的情況吧。

假設Alice在文檔開頭插入一行，並且Bob在文檔末尾添加一行。他們都上傳了他們的改
動。大多數系統將自動給出一個合理的處理方式：接受且合併他們的改動，這樣Alice和
Bob兩人的改動都會生效。

現在假設Alice和Bob對檔案的同一行做了不同的改動。如果沒有人工參與的話，這個沖
突是無法解決的。第二個人在上載檔案時，會收到 _合併衝突_ 的通知，要麼用一個人
的改動覆蓋另一個的，要麼完全修訂這一行。

更複雜的情況也可能出現。版本控制系統自己處理相對簡單的情況，把困難的情況留給
人來處理。它們的行為通常是可配置的。

