TortoiseSVN 帮助教程(二)—— 相关控制理论


前言

  文章内容来源于翻译TortoiseSVN软件帮助文档。

  本章是Subversion书籍中同一章的稍作修改。
  本章是对Subversion的简短介绍。 如果您不熟悉版本控制,那么本章绝对适合您。 我们将从讨论通用版本控制概念开始,深入探讨Subversion背后的特定思想,并展示一些使用Subversion的简单示例。
  即使本章中的示例显示了人们共享程序源代码的集合,也请记住Subversion可以管理任何类型的文件集合-它不仅限于帮助计算机程序员。


一、库

  Subversion是一个用于共享信息的集中式系统。 它的核心是存储库,它是数据的中央存储。 该存储库以文件系统树的形式存储信息-文件系统树是文件和目录的典型层次结构。 任何数量的客户端都连接到存储库,然后读取或写入这些文件。 通过写入数据,客户可以将信息提供给其他人; 通过读取数据,客户端将从他人那里接收信息。
在这里插入图片描述
  那么为什么这很有趣? 到目前为止,这听起来像是典型文件服务器的定义。 确实,存储库是一种文件服务器,但是它不是您通常的品种。 Subversion存储库之所以与众不同,是因为它能够记住写入的所有更改:每个文件的每个更改,甚至是目录树本身的更改,例如文件和目录的添加,删除和重新排列。

  客户端从存储库中读取数据时,通常只能看到文件系统树的最新版本。 但是客户端也可以查看文件系统的先前状态。 例如,客户可以询问一些历史性问题,例如“该目录在上星期三包含了什么? ”或“谁是最后一个更改此文件的人,他们做了什么更改? 这些是任何版本控制系统的核心问题:旨在记录和跟踪随时间变化的数据的系统。

二、版本模型

  所有版本控制系统都必须解决相同的基本问题:系统将如何允许用户共享信息,但又防止他们意外踩到对方的脚? 用户很容易意外覆盖存储库中彼此的更改。

1. 文件共享问题

  考虑以下情况:假设我们有两个同事,Harry和Sally。 他们每个人都决定同时编辑同一存储库文件。 如果Harry首先将他的更改保存到存储库中,那么(稍后)Sally可能会使用她自己的新文件版本意外覆盖它们。 虽然Harry的文件版本不会永远丢失(因为系统会记住所有更改),但Harry所做的任何更改都不会出现在Sally的文件的新版本中,因为她从未看到过Harry的更改。 Harry的工作仍然有效地丢失或至少在最新版本的文件中丢失了。 这绝对是我们要避免的情况!
在这里插入图片描述

2. 锁定-修改-解锁解决方案

  许多版本控制系统使用锁定-修改-解锁模型来解决此问题,这是一个非常简单的解决方案。 在这样的系统中,存储库一次仅允许一个人更改文件。 首先,Harry必须先锁定文件,然后才能开始对其进行更改。 锁定文件就像从图书馆借书。 如果Harry锁定了文件,则Sally无法对其进行任何更改。 如果她尝试锁定文件,则存储库将拒绝该请求。 她所能做的就是读取文件,然后等待Harry完成更改并释放锁。 Harry解锁文件后,轮到他了,现在Sally可以通过锁定和编辑来轮到她。
在这里插入图片描述
锁定-修改-解锁模型的问题在于它有点限制性,并且经常成为用户的障碍:

  • 锁定可能会导致管理问题。有时,Harry会锁定文件,然后忘记它。同时,由于Sally仍在等待编辑文件,因此她的双手被绑住了。然后哈利去度假。现在,Sally必须获得管理员才能释放Harry的锁。这种情况最终导致大量不必要的延迟和时间浪费。

  • 锁定可能会导致不必要的序列化。如果Harry正在编辑文本文件的开头,而Sally只想编辑同一文件的结尾怎么办?这些更改根本不重叠。假设更改已正确合并在一起,他们可以轻松地同时编辑文件,并且不会造成太大危害。在这种情况下,他们无需轮流使用。

  • 锁定可能会产生错误的安全感。假设Harry锁定并编辑文件A,而Sally同时锁定并编辑文件B。但是,假设A和B相互依赖,并且对它们所做的更改在语义上是不兼容的。突然,A和B不再合作。锁定系统无法阻止此问题-但是以某种方式提供了错误的安全感。很容易让Harry和Sally想象到,通过锁定文件,每个文件都开始一项安全,隔离的任务,因此阻止了他们早日讨论其不兼容的更改。

3. 复制-修改-合并解决方案

  Subversion,CVS和其他版本控制系统使用复制-修改-合并模型作为锁定的替代方法。在此模型中,每个用户的客户端都读取存储库并创建文件或项目的个人工作副本。然后,用户可以并行工作,修改其私有副本。最后,私有副本将合并在一起成为新的最终版本。版本控制系统通常会协助合并,但是最终要由人来负责使其正确实现。

  这是一个例子。假设Harry和Sally各自创建了同一项目的工作副本,并从存储库复制了该副本。它们可以同时工作,并在其副本中对同一文件A进行更改。 Sally首先将所做的更改保存到存储库中。当Harry稍后尝试保存其更改时,存储库会通知他其文件A已过期。换句话说,自上次复制文件以来,存储库中的文件A已有某种更改。因此,Harry要求他的客户将存储库中的任何新更改合并到他的文件A的工作副本中。Sally的更改可能与他自己的更改不重叠;因此,一旦他将两组变更都集成在一起,便将其工作副本保存回存储库中。

  • Copy-Modify-Merge Solution
    在这里插入图片描述
  • Copy-Modify-Merge Continued
    Copy-Modify-Merge Continued

  但是,如果Sally的变化与Harry的变化重叠呢?然后怎样呢?这种情况称为冲突,通常不是什么大问题。当Harry要求客户将最新的存储库更改合并到他的工作副本中时,他的文件A副本会以某种方式标记为处于冲突状态:他将能够看到两组冲突的更改,并在它们之间进行手动选择。请注意,软件无法自动解决冲突。只有人类才能理解并做出必要的明智选择。一旦Harry手动解决了重叠的更改(也许是通过与Sally讨论冲突!),他就可以安全地将合并的文件保存回存储库中。

  复制-修改-合并模型听起来可能有些混乱,但是在实践中,它运行非常平稳。用户可以并行工作,而无需彼此等待。当他们使用相同的文件时,事实证明,大多数并发更改根本不会重叠。冲突很少发生。解决冲突所需的时间远远少于锁定系统所花费的时间。

  最后,所有这些归结为一个关键因素:用户交流。当用户沟通不畅时,语法和语义冲突都会增加。没有系统可以强迫用户进行完美的通信,也没有系统可以检测到语义冲突。因此,毫无根据地误以为锁定系统将以某种方式防止冲突;在实践中,锁定似乎对生产力的抑制比其他任何因素都更大。

  在一种常见情况下,锁定-修改-解锁模型会更好地出现,那就是您拥有不可合并的文件。例如,如果您的存储库包含一些图形图像,并且两个人同时更改了图像,则无法将这些更改合并在一起。哈利或莎莉都将丢失他们的更改。

三、覆盖动作

1. 工作副本

  您已经阅读了有关工作副本的信息;现在,我们将演示Subversion客户端如何创建和使用它们。

  Subversion工作副本是本地系统上的普通目录树,其中包含文件集合。您可以根据需要编辑这些文件,如果它们是源代码文件,则可以按常规方式从它们编译程序。您的工作副本是您自己的私人工作区域:Subversion永远不会合并其他人的更改,也不会将您自己的更改提供给其他人,除非您明确指示这样做。

  在对工作副本中的文件进行了一些更改并确认它们可以正常工作后,Subversion为您提供了一些命令,可将您的更改发布给与您一起在项目中工作的其他人(通过写入存储库)。如果其他人发布自己的更改,Subversion将为您提供命令以将这些更改合并到您的工作目录中(通过从存储库中读取)。

  工作副本还包含一些其他文件,这些文件由Subversion创建和维护,以帮助其执行这些命令。特别是,您的工作副本包含一个名为.svn的子目录,也称为工作副本管理目录。此管理目录中的文件有助于Subversion识别哪些文件包含未发布的更改,以及哪些文件相对于其他人的工作而言是过时的。在1.7之前的版本中,工作副本的每个版本目录中都维护.svn管理子目录。 Subversion 1.7采用了一种完全不同的方法,每个工作副本现在只有一个管理子目录,该目录是该工作副本根目录的直接子目录。

  典型的Subversion存储库通常包含多个项目的文件(或源代码)。通常,每个项目都是存储库文件系统树中的子目录。在这种安排中,用户的工作副本通常将对应于存储库的特定子树。

  例如,假设您有一个包含两个软件项目的存储库。
在这里插入图片描述
  换句话说,存储库的根目录具有两个子目录:paint和calc。

  要获得工作副本,必须检出存储库的某些子树。 (检出一词听起来似乎与锁定或保留资源有关,但事实并非如此;它只是为您创建项目的私有副本。)

  假设您对button.c进行了更改。由于.svn目录会记住文件的修改日期和原始内容,因此Subversion可以告诉您已更改了文件。但是,Subversion不会公开您所做的更改,除非您明确告知您。发布更改的行为通常称为将更改提交(或检入)存储库。

  要将更改发布给其他人,可以使用Subversion的commit命令。

  现在,您对button.c的更改已提交到存储库;如果另一个用户检出/ calc的工作副本,他们将在文件的最新版本中看到您的更改。

  假设您有一个协作者Sally,他在您同时检出了/ calc的工作副本。当您将更改提交到button.c时,Sally的工作副本将保持不变。 Subversion仅在用户请求时修改工作副本。

  为了使她的项目保持最新状态,Sally可以使用Subversion update命令要求Subversion更新她的工作副本。这会将您所做的更改以及她检出后所做的所有其他更改合并到她的工作副本中。

  请注意,Sally不需要指定要更新的文件。 Subversion使用.svn目录中的信息以及存储库中的更多信息来确定需要更新哪些文件。

2. 储存库网址

  可以通过许多不同的方法(在本地磁盘上或通过各种网络协议)访问Subversion存储库。 但是,存储库位置始终是URL。 URL模式指示访问方法:

模式接入方式
file://在本地或网络驱动器上直接访问存储库。
http://通过WebDAV协议访问支持Subversion的Apache服务器。
https://与http://相同,但具有SSL加密。
SVN://通过自定义协议对svnserve服务器的未经身份验证的TCP / IP访问。
svn+ssh://通过自定义协议对svnserve服务器进行身份验证,加密的TCP / IP访问。

  在大多数情况下,Subversion的URL使用标准语法,允许将服务器名称和端口号指定为URL的一部分。 尽管可以将file://访问方法用于本地访问,但是它可以与网络主机的UNC路径一起使用。 因此,URL的格式为file:// hostname / path / to / repos。 对于本地计算机,URL的主机名部分必须不存在或为localhost。 因此,本地路径通常以三个斜杠出现:file:/// path / to / repos。

  此外,Windows平台上的file://方案的用户将需要使用非官方的“标准”语法来访问与客户端当前工作驱动器位于同一台计算机但位于不同驱动器上的存储库。 以下两种URL路径语法中的任何一种都可以使用,其中X是存储库所在的驱动器:

file:///X:/path/to/repos

file:///X|/path/to/repos

请注意,即使Windows路径的本机(非URL)形式使用反斜杠,URL也会使用普通斜杠。

您可以通过网络共享访问FSFS存储库,但是由于各种原因,不建议这样做:

  • 您为所有用户提供了直接写访问权,因此他们可能会意外删除或损坏存储库文件系统。
  • 并非所有网络文件共享协议都支持Subversion所需的锁定; 有一天,您会发现您的存储库已被巧妙破坏。
  • 您必须以正确的方式设置访问权限。 SAMBA在这方面特别困难。
  • 如果有人安装了较新版本的客户端,从而升级了存储库格式,那么其他人将无法访问该存储库,除非他们也升级到了新的客户端版本。

3. 修订版本

  svn commit操作可以将更改发布为单个原子事务,从而发布对任意数量的文件和目录。在工作副本中,您可以更改文件的内容,创建,删除,重命名和复制文件和目录,然后将整个更改集作为一个单元提交。

  在存储库中,每个提交都被视为原子事务:要么所有提交更改都发生,要么都不发生。面对程序崩溃,系统崩溃,网络问题和其他用户的操作,Subversion保留了这种原子性。

  每次存储库接受提交时,都会创建文件系统树的新状态,称为修订。每个修订版都分配有一个唯一的自然数,该数字比上一个修订版的数大一个。新创建的存储库的初始版本编号为零,除了空的根目录外,什么都没有。

  可视化存储库的一种不错的方法是使用一系列树。想象一下一个修订号数组,从0开始,从左到右延伸。每个修订版号的下面都有一个文件系统树,每个树都是存储库每次提交后查找方式的“快照”。
在这里插入图片描述

全局修订号

与许多其他版本控制系统的版本不同,Subversion的修订版号适用于整个树,而不是单个文件。 每个修订号都会选择一整棵树,在进行某些更改后会选择存储库的特定状态。 另一种考虑方式是修订版N代表第N次提交后存储库文件系统的状态。 当Subversion用户谈论"foo.c的修订版5"时,他们实际上的意思是"修订版5中出现的foo.c"。请注意,一般而言,文件的修订版N和M不一定相同!

  重要的是要注意,工作副本并不总是对应于存储库中的任何单个修订版; 它们可能包含来自多个不同版本的文件。 例如,假设您从最新修订版为4的存储库中签出工作副本:

calc/Makefile:4
integer.c:4
button.c:4

  目前,此工作目录与存储库中的修订版4完全对应。 但是,假设您对button.c进行了更改,然后提交了该更改。 假设没有其他提交,则您的提交将创建存储库的修订版5,现在您的工作副本将如下所示:

calc/Makefile:4
integer.c:4
button.c:5

  假设此时,Sally提交了对integer.c的更改,创建了修订版6。如果使用svn update来更新工作副本,那么它将看起来像这样:

calc/Makefile:6
integer.c:6
button.c:6

  Sally对integer.c所做的更改将出现在您的工作副本中,并且您的更改仍将存在于button.c中。 在此示例中,修订版本4、5和6中Makefile的文本相同,但是Subversion将使用修订版本6标记Makefile的工作副本,以指示该版本仍然是最新的。 因此,在工作副本的顶部进行干净的更新后,它通常将恰好对应于存储库中的一个修订。

4. 工作副本如何跟踪存储库

  对于工作目录中的每个文件,Subversion在.svn /管理区域中记录两条重要信息:

  • 您的工作文件基于哪个修订版(称为文件的工作修订版)

  • 记录本地存储库上次更新本地副本的时间戳。

  有了这些信息,通过与存储库进行对话,Subversion可以判断工作文件处于以下四个状态中的哪个状态:

  • 不变,最新
    该文件在工作目录中保持不变,并且自其工作修订版以来,尚未对该文件进行任何更改。提交文件将不执行任何操作,而文件的更新将不执行任何操作。

  • 本地更改,当前
    该文件已在工作目录中更改,并且自其基本修订版以来,尚未对该文件进行任何更改。存在尚未提交到存储库的本地更改,因此,提交文件将成功发布更改,而文件的更新将不起作用。

  • 不变且过时
    该文件在工作目录中尚未更改,但是在存储库中已更改。该文件最终应进行更新,以使其与公共修订版保持一致。提交文件不会执行任何操作,并且文件的更新会将最新更改折叠到您的工作副本中。

  • 本地更改且已过时
    该文件在工作目录和存储库中均已更改。提交文件将失败,并显示过期错误。该文件应首先更新;更新命令将尝试将公共更改与本地更改合并。如果Subversion无法以合理的方式自动完成合并,则将其留给用户解决冲突。

总结

在本章中,讨论了许多基本的Subversion概念:

  • 介绍了中央存储库,客户端工作副本以及存储库修订树数组的概念;
  • 已经看到了一些简单的示例,说明了两个协作者如何使用“复制-修改-合并”模型使用Subversion发布和接收彼此的更改;
  • 已经讨论了Subversion跟踪和管理工作副本中信息的方式;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值