== 入门 ==

我将用类比方式来介绍版本控制的概念。更严谨的解释参见
http://en.wikipedia.org/wiki/Revision_control[维基百科版本修订控制条目]。

=== 工作是玩 ===

我从小就玩电脑游戏。相反，我只是在长大后才开始使用版本控制系统。我想我并不特
殊，并且，对比两者工作方式可使这些概念更易解释，也易于理解。

编写代码，或编辑文档和玩游戏差不多。在你做出了很多进展之后，你最好保存一下。
去做这个，会点击你所信任的编辑器保存按钮就好了。

但这将覆盖老版本。就像那些学校里玩的老游戏，只有一个存档：你确实可以保存，但
你不能回到更老的状态了。这真让人扫兴，因为那个状态可能恰好保存了这个游戏特别
有意思一关，说不定哪天你想再玩一下呢。或者更糟糕的，你当前的保存是个必败局，
这样你就不得不从头开始玩了。

=== 版本控制 ===

在编辑的时候，如果想保留旧版本，你可以将文件“另存为”一个不同的文件，或在保
存之前将文件拷贝到别处。你可能压缩这些文件以节省空间。这是一个初级的靠手工的
版本控制方式。游戏软件早就提高了这块，很多都提供多个基于时间戳的自动存档槽。

让我们看看稍稍复杂的情况。比如你有很多放在一起的文件，比如项目源码，或网站文
件。现在如你想保留旧版本，你不得不把整个目录存档。手工保存多个版本很不方便，
而且很快会耗费巨大。

在一些电脑游戏里，一个存档真的包含在一个充满文件的目录里。这些游戏为玩家屏蔽
了这些细节，并提供一个方便易用的界面来管理该目录的不同版本。

版本控制系统也没有两样。两者提供友好的界面，来管理目录里的东西。你可以频繁保
存，也可以之后加载任一保存。不像大多计算机游戏，版本控制系统通常精于节省存储
空间。一般情况如果两个版本间只有少数文件的变更，每个文件的变更也不大，那就只
存储差异的部分，而不是把全部拷贝的都保存下来，以节省存储空间。

=== 分布控制 ===

现在设想一个很难的游戏。太难打了，以至于世界各地很多骨灰级玩家决定组队，分享
他们游戏存档以攻克它。Speedrun们就是实际中的例子：在同一个游戏里，玩家们分别
攻克不同的等级，协同工作以创造惊人战绩。

你如何搭建一个系统，使得他们易于得到彼此的存档？并易于上载新的存档？

在过去，每个项目都使用中心式版本控制。某个服务器上放所有保存的游戏记录。其他
人就不用了。每个玩家在他们机器上最多保留几个游戏记录。当一个玩家想更新进度时
候，他们需要把最新进度从主服务器下载下来，玩一会儿，保存并上载到主服务器以供
其他人使用。

假如一个玩家由于某种原因，想得到一个较旧版本的游戏进度怎么样？或许当前保存的
游戏是一个注定的败局，因为某人在第三级忘记捡某个物品；他们希望能找到最近一个
可以完成的游戏记录。或者他们想比较两个旧版本间的差异，来估算某个特定玩家干了
多少活。

查看旧版本的理由有很多，但检查的办法都是一样的。他们必须去问中心服务器要那个
旧版本的记录。需要的旧版本越多，和服务器的交互就越多。

新一代的版本控制系统，Git就是其中之一，是分布式的，可以被认作广义上的中心式系
统。从主服务器下载时玩家会得到所有保存的记录，而不仅是最新版。这看起来他们好
像把中心服务器做了个镜像。

最初的克隆操作可能比较费时，特别当有很长历史的时，但从长远看这是值得的。一个
显而易见的好处是，当查看一个旧版本时，不再需要和中心服务器通讯了。

=== 一个误区 ===

一个很常见的错误观念是，分布式系统不适合需要官方中心仓库的项目。这与事实并不
相符。给谁照相也不会偷走他们的灵魂。类似地，克隆主仓库并不降低它的重要性。

一般来说，一个中心版本控制系统能做的任何事，一个良好设计的分布式系统都能做得
更好。网络资源总要比本地资源耗费更费。不过我们应该在稍后分析分布式方案的缺点，
这样人们才不会按照习惯做出错误的比较。

一个小项目或许只需要分布式系统提供的一小部分功能，但是，在项目很小的时候，应
该用规划不好的系统？就好比说，在计算较小数目的时候应该使用罗马数字？

而且，你的项目的增长可能会超出你最初的预期。从一开始就使用Git好似带着一把瑞士
军刀，尽管你很多时候只是用它来开开瓶盖。某天你迫切需要一把改锥，你就会庆幸你
所有的不单单是一个启瓶器。

=== 合并冲突 ===

对于这个话题，电脑游戏的类比显得不够用。那让我们再来看看文档编辑的情况吧。

假设Alice在文档开头插入一行，并且Bob在文档末尾添加一行。他们都上传了他们的改
动。大多数系统将自动给出一个合理的处理方式：接受且合并他们的改动，这样Alice和
Bob两人的改动都会生效。

现在假设Alice和Bob对文件的同一行做了不同的改动。如果没有人工参与的话，这个冲
突是无法解决的。第二个人在上载文件时，会收到 _合并冲突_ 的通知，要么用一个人
的改动覆盖另一个的，要么完全修订这一行。

更复杂的情况也可能出现。版本控制系统自己处理相对简单的情况，把困难的情况留给
人来处理。它们的行为通常是可配置的。

