版本模型

版本控制系统的中心任务是使人们可以合作编辑和分享数据。但是不同的系统使用不同的策略来达到这一目的。

文件共享的难题

所有版本控制系统都必须解决相同的基本难题:如何使系统允许人们共享信息,又能防止人们意外互相干扰。由于不小心而覆盖了别人对资料库的改动这样的事太容易发生了。

看看如图 2.2 “需要避免的问题”所演示的场景。假设有两个合作者,Harry和Sally。他们同时决定编辑相同的资料库文件。 如果Harry先把他的改动保存到资料库,那么可能(一段时间后)Sally会不小心用自己的新版文件覆盖了那些文件。虽然Harry版的文件不会丢失(因为系统记住了所有改动),但是Harry的任何改动都不会在Sally的新版文件中出现,因为她开始修改文件时并没有看到Harry的改动。Harry的工作从效果来看是丢失了,至少在最新版的文件里没有体现,可能只是处于偶然。这绝对是我们要避免地情形。won't be

图 2.2. 需要避免的问题

需要避免的问题

解决方案:锁定-修改-解锁

很多版本控制系统用一种锁定-修改-解锁模型来解决这个难题。在这种系统中,资料库在某一时间只允许一个人修改某一文件。首先,Harry必须“锁定”这个文件,然后才能开始修改它。锁定一个文件有点像从图书馆里借书;如果Harry已经锁定了一个文件,那么Sally就不能对这文件作任何修改。如果她企图锁定这个文件,资料库将拒绝这个请求。她只能读这个文件,然后等Harry完成了他的修改并释放了他的锁。在Harry解锁了这个文件后,他这一轮修改结束了,现在Sally可以通过锁定和编辑来进行她这轮修改。图 2.3 “图2.3 解决方案:锁定-修改-解锁”展示了这个简单的解决办法 demonstrates this simple solution.

图 2.3. 图2.3 解决方案:锁定-修改-解锁

图2.3 解决方案:锁定-修改-解锁

锁定-修改-解锁 模型的问题是它有点限制太强了,以至于常常成为人们的绊脚石:

  • 加锁可能引起管理上的问题。 有时Harry锁定了一个文件却忘了,Sally因为在一直等着修改这个文件,所以没法工作。接着Harry休假去了。现在Sally只好去找管理员来解开Harry的锁。这种情况会导致很多不必要的延误和时间上的浪费。

  • 加锁可能引起不必要的串行化。 如果当Harry在编辑一个文本文件的开头时, Sally只是想编辑同一文件的结尾时怎么办?这些修改根本不会互相交叠。他们可以同时编辑,如果修改能被恰当的合并,就不会有大的损害发生。在这种情况下没有必要非得轮着来。

  • 加锁可能带来安全的错觉。 假如Harry锁定并编辑了文件A,同时Sally锁定并编辑了文件B。但是A和B是互相依赖的,从而对他们的改动在语义上无法兼容。这会导致突然间A和B不能一起工作了。加锁系统对阻止这样的问题发生无能为力,但是在一定程度上给人以安全的错觉。很容易导致Harry和Sally认为有文件锁定,他们做的是安全的,隔离的工作,犯不着提前讨论他们的互不兼容的修改。

解决方案:拷贝-修改-合并

Subversion,CVS,和其他一些版本控制系统使用拷贝-修改-合并模型,而不用加锁。在这个模型中,每个用户的客户端连接到项目资料库并创建一个个人的工作副本--资料库中文件和目录的本地映像。然后用户们并行的工作,修改他们私有的副本。最后这些私有副本被合并到一起成为一个新的最终的版本。版本控制系统通常会帮助做合并,但是根本上还是靠人来负责正确的合并。

这里举一个例子。假如Harry和Sally都从资料库拷贝建立了同一项目的工作副本。他们并行的工作,分别对他们副本中相同的文件A做了修改。Sally先把她的修改保存到资料库中。当不久后Harry要保存他的修改时,资料库会通知他他的文件A过时了。换句话说,资料库中的文件A在他拷贝后有一些新的修改。于是,Harry让他的客户端程序把资料库中的修改合并到他的文件A的副本里。可能Sally的修改和他的不重叠,于是只要他合并了二者的修改,就可以把他的工作副本保存回资料库。 图 2.4 “解决方案:拷贝-修改-合并”图 2.5 “解决方案:拷贝-修改-合并(续)”演示了这一过程。

图 2.4. 解决方案:拷贝-修改-合并

解决方案:拷贝-修改-合并

图 2.5. 解决方案:拷贝-修改-合并(续)

解决方案:拷贝-修改-合并(续)

但是如果Sally的改动和Harry的重叠怎么办?接下来呢?这种情况叫做冲突,通常不是什么大问题。当Harry让他的客户程序把资料库中最新的的修改合并到他们文件中时,他的文件A的副本会被用某种方式标记成冲突状态:他可以看到两个互相冲突的修改,从而手工做出选择。注意,软件无法自动解决冲突,只有人可以理解并做必要的、智能的选择。只要Harry手动解决了这些重叠的修改--可能在和Sally讨论后--他就可以安全的把合并后的文件保存回资料库了。

拷贝-修改-合并模型听起来有点混乱,但在实践中,它工作的非常稳定。用户们可以并行工作,从来用不着等别人。当他们在同一些文件上工作时,实践表明大部分同时做的修改根本不会互相重叠,冲突不经常发生。而且花费在解决冲突上的时间比锁定系统所浪费的时间少的多。

最后,这些问题都可以归结到一个关键因素:用户沟通。如果用户们沟通不好,语义和语法上的冲突都会增加。没有那个系统能强制用户完美的沟通,没有那个系统能检测语义上的冲突。所以,不要被这样的虚假承诺蒙蔽:加锁系统可以在某种程度上防止冲突。实际上,看起来加锁比别的系统更制约生产力。