这份文档是用来描述 Subversion 1.1 的。如果你正在运行更新版本的 Subversion,我们强烈建议你访问 https://svnbooks.subversion.org.cn/ 并查阅适合你 Subversion 版本的这本书。
版本控制系统的核心任务是支持协作编辑和数据共享。但不同的系统使用不同的策略来实现这一点。
所有版本控制系统都必须解决同一个基本问题:系统如何允许用户共享信息,但又防止他们意外地踩到彼此的脚?用户很容易意外地覆盖彼此在存储库中的更改。
考虑 图 2.2,"要避免的问题" 中所示的情况。假设我们有两个同事,哈利和莎莉。他们都决定同时编辑同一个存储库文件。如果哈利先将他的更改保存到存储库,那么 (几分钟后) 莎莉可能会意外地用她自己的新版本文件覆盖它们。虽然哈利版本的这个文件不会永远丢失 (因为系统会记住每次更改),但哈利所做的任何更改 不会 出现在莎莉更新版本的这个文件中,因为她一开始就没有看到哈利的更改。哈利的工作实际上是丢失了 - 或者至少从这个文件的最新版本中消失了 - 而且很可能是意外发生的。这绝对是我们想要避免的情况!
许多版本控制系统使用 锁定-修改-解锁 模型来解决这个问题。在这种系统中,存储库一次只允许一个人更改一个文件。哈利必须先“锁定”这个文件,然后才能开始对其进行更改。锁定一个文件就像从图书馆借一本书一样;如果哈利锁定了某个文件,那么莎莉就无法对其进行任何更改。如果她试图锁定这个文件,存储库将拒绝请求。她只能阅读这个文件,并等待哈利完成他的更改并释放他的锁定。哈利解锁这个文件后,他的回合就结束了,现在莎莉可以通过锁定和编辑来轮到她了。 图 2.3,"锁定-修改-解锁解决方案" 演示了这个简单的解决方案。
锁定-修改-解锁模型的问题是它有点限制性,并且经常成为用户的障碍
锁定可能会导致管理问题。 有时候哈利会锁定一个文件,然后忘记它。与此同时,因为莎莉还在等待编辑这个文件,所以她被束缚住了。然后哈利去度假了。现在莎莉必须让管理员释放哈利的锁定。这种情况最终会导致很多不必要的延迟和时间浪费。
锁定可能会导致不必要的序列化。 如果哈利正在编辑文本文件的开头,而莎莉只是想编辑同一个文件的结尾怎么办?这些更改根本没有重叠。他们可以很容易地同时编辑这个文件,并且不会造成很大的伤害,假设这些更改被正确地合并在一起。在这种情况下,他们没有必要轮流进行。
锁定可能会造成错误的安全感。 假设哈利锁定并编辑了文件 A,而莎莉同时锁定并编辑了文件 B。但假设 A 和 B 相互依赖,并且对每个文件所做的更改在语义上是不兼容的。突然 A 和 B 不再一起工作了。锁定系统无力阻止这个问题 - 但它却以某种方式提供了一种错误的安全感。哈利和莎莉很容易想象,通过锁定文件,每个人都在开始一个安全、孤立的任务,因此不需要在早期讨论他们的不兼容更改。
Subversion、CVS 和其他版本控制系统使用 复制-修改-合并 模型作为锁定的替代方案。在这个模型中,每个用户的客户端都会联系项目存储库并创建一个个人 工作副本 - 存储库文件和目录的本地反映。用户然后并行工作,修改他们的私有副本。最后,私有副本被合并成一个新的、最终的版本。版本控制系统通常会帮助合并,但最终由人来负责正确地进行合并。
以下是一个例子。假设哈利和莎莉都从存储库中复制创建了同一个项目的副本。他们同时工作,并在他们的副本中对同一个文件 A 进行更改。莎莉先将她的更改保存到存储库。当哈利尝试稍后保存他的更改时,存储库会通知他,他的文件 A 已过期。换句话说,存储库中的文件 A 已经在他上次复制它之后发生了变化。所以哈利要求他的客户端将存储库中的任何新更改 合并 到他工作副本中的文件 A。很有可能莎莉的更改与他自己的更改没有重叠;所以一旦他将两组更改都整合起来,他就会将他的工作副本保存回存储库。 图 2.4,"复制-修改-合并解决方案" 和 图 2.5,"复制-修改-合并解决方案(续)" 展示了这个过程。
但是,如果莎莉的更改 确实 与哈利的更改重叠怎么办?然后会发生什么?这种情况被称为 冲突,通常不是什么大问题。当哈利要求他的客户端将最新的存储库更改合并到他的工作副本中时,他的文件 A 副本以某种方式被标记为处于冲突状态:他将能够看到两组冲突的更改,并手动选择它们。请注意,软件无法自动解决冲突;只有人类能够理解并做出必要的明智选择。一旦哈利手动解决了重叠的更改 - 也许是在与莎莉讨论之后 - 他就可以安全地将合并后的文件保存回存储库。
复制-修改-合并模型听起来可能有点混乱,但实际上,它运行得非常流畅。用户可以并行工作,从不互相等待。当他们在同一个文件上工作时,事实证明他们大部分的并发更改根本没有重叠;冲突很少见。而且解决冲突所需的时间远远少于锁定系统所浪费的时间。
归根结底,这一切都归结于一个关键因素:用户沟通。当用户沟通不畅时,语法和语义冲突都会增加。没有系统能够强迫用户完美地沟通,也没有系统能够检测语义冲突。因此,没有必要被锁定系统会以某种方式防止冲突的错误承诺所迷惑;实际上,锁定似乎比其他任何事情都更能抑制生产力。