使用Subversion进行版本控制之1到2章

来源:百度文库 编辑:神马文学网 时间:2024/03/28 23:54:15
使用Subversion进行版本控制

使用Subversion进行版本控制

针对 Subversion 1.1

(本书编译对应1876修订版本)

Ben Collins-Sussman

Brian W. Fitzpatrick

C. Michael Pilato

版权 © 2002, 2003, 2004, 2005 Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato

本书使用创作共用署名许可证,可以通过访问http://creativecommons.org/licenses/by/2.0/或者发送邮件到Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA来查看本许可证的内容。

(TBA)


目录

译者序
前言
序言
读者
怎样阅读本书
本书约定
排版习惯
图标
本书组织结构
Subversion 1.1的新特性
这本书是免费的
致谢
来自Ben Collins-Sussman
来自Brian W. Fitzpatrick
来自C. Michael Pilato
1. 介绍
Subversion是什么?
Subversion的历史
Subversion的特性
Subversion的架构
安装Subversion
Subversion的组件
快速入门
2. 基本概念
版本库
版本模型
文件共享的问题
锁定-修改-解锁 方案
拷贝-修改-合并 方案
Subversion实战
工作拷贝
修订版本
工作拷贝怎样追踪版本库
修订版本混合的限制
摘要
3. 指导教程
帮助!
导入
修订版本: 号码、关键字和日期,噢,我的!
修订版本号
修订版本关键字
修订版本日期
初始化的Checkout
基本的工作周期
更新你的工作拷贝
修改你的工作拷贝
检查你的修改
svn status
svn diff
svn revert
解决冲突(合并别人的修改)
手工合并冲突
拷贝覆盖你的工作文件
下注:使用svn revert
提交你得修改
检验历史
svn log
svn diff
比较本地修改
比较工作拷贝和版本库
比较版本库与版本库
svn cat
svn list
关于历史的最后一个词
其他有用的命令
svn cleanup
svn import
摘要
4. 分支与合并
什么是分支?
使用分支
创建分支
在分支上工作
分支背后的关键概念
在分支间拷贝修改
拷贝特定的修改
合并背后的关键概念
合并的最佳实践
手工追踪合并
预览合并
合并冲突
关注还是忽视祖先
常见用例
合并一条分支到另一支
取消修改
找回删除的项目
常用分支模式
发布分支
特性分支
转换工作拷贝
标签
建立最简单的标签
建立复杂的标签
分支维护
版本库布局
数据的生命周期
摘要
5. 版本库管理
版本库基本知识
理解事务和修订版本
未受版本控制的属性
版本库数据存储
Berkeley DB
FSFS
版本库的创建和配置
钩子脚本
Berkeley DB配置
版本库维护
管理员的工具箱
svnlook
svnadmin
svndumpfilter
svnshell.py
Berkeley DB工具
版本库清理
管理磁盘空间
版本库的恢复
版本库的移植
版本库备份
添加项目
选择一种版本库布局
创建布局,导入初始数据
摘要
6. 配置服务器
概述
网络模型
请求和响应
客户端凭证缓存
svnserve,一个自定义的服务器
调用服务器
内置的认证和授权
创建一个用户文件和域
设置访问控制
SSH认证和授权
SSH配置技巧
初始设置
控制调用的命令
httpd,Apache的HTTP服务器
必备条件
基本的Apache配置
认证选项
基本HTTP认证
SSL证书管理
授权选项
整体访问控制
每目录访问控制
关闭路径为基础的检查
额外的糖果
版本库浏览
其它特性
支持多种版本库访问方法
7. 高级主题
运行配置区
配置区布局
配置和Windows注册表
配置选项
服务器
config
属性
为什么需要属性?
处理属性
特别属性
svn:executable
svn:mime-type
svn:ignore
svn:keywords
svn:eol-style
svn:externals
svn:special
自动属性设置
Peg和实施修订版本
外部定义
卖主分支
常规的卖主分支管理过程
svn_load_dirs.pl
本地化
理解地区
Subversion对地区的支持
Subversion版本库URL
8. 开发者信息
分层的库设计
版本库层
版本库访问层
RA-DAV(使用HTTP/DAV版本库访问)
RA-SVN(自定义协议版本库访问)
RA-Local(直接版本库访问)
你的RA库在这里
客户端层
使用API
Apache可移植运行库
URL和路径需求
使用C和C++以外的语言
进入工作拷贝的管理区
条目文件
原始拷贝和属性文件
WebDAV
使用内存池编程
为Subversion做贡献
加入社区
取得源代码
开始熟悉社区政策
作出修改并测试
贡献你的修改
9. Subversion完全参考
Subversion命令行客户端:svn
svn选项
svn子命令
svn add
svn blame
svn cat
svn checkout
svn cleanup
svn commit
svn copy
svn delete
svn diff
svn export
svn help
svn import
svn info
svn list
svn log
svn merge
svn mkdir
svn move
svn propdel
svn propedit
svn propget
svn proplist
svn propset
svn resolved
svn revert
svn status
svn switch
svn update
svnadmin
svnadmin Switches
svnadmin Subcommands
svnadmin create
svnadmin deltify
svnadmin dump
svnadmin help
svnadmin hotcopy
svnadmin list-dblogs
svnadmin list-unused-dblogs
svnadmin load
svnadmin lstxns
svnadmin recover
svnadmin rmtxns
svnadmin setlog
svnadmin verify
svnlook
svnlook选项
svnlook
svnlook author
svnlook cat
svnlook changed
svnlook date
svnlook diff
svnlook dirs-changed
svnlook help
svnlook history
svnlook info
svnlook log
svnlook propget
svnlook proplist
svnlook tree
svnlook uuid
svnlook youngest
svnserve
svnserve选项
svnversion
svnversion
mod_dav_svn
mod_dav_svn Configuration Directives
A. Subversion对于CVS用户
修订版本号现在不同了
目录的版本
更多离线操作
区分状态和更新
分支和标签
元数据属性
冲突解决
二进制文件和转化
版本化的模块
认证
转化CVS版本库到Subversion
B. 故障解决
共同问题
使用Subversion的问题
每当我尝试访问版本库,我的Subversion客户端挂起。
每当我尝试运行svn,它告诉我工作拷贝已经锁定。
我在查找和打开版本库时得到错误,而我知道我的版本库URL是正确的。
我怎样在file://的URL中指定一个Windows驱动器盘符?
通过网络对Subversion版本库进行写操作发生问题。
在Windows XP下,Subversion服务器有时候看起来发送损坏的数据。
跟踪Subversion客户端和Apache服务器通话最好的方法是什么?
我刚刚编译了二进制分发版本,当我尝试检出Subversion,我得到一个“Unrecognized URL scheme”错误。
为什么svn revert命令要有一个明确的目标?为什么缺省不是递归的?它的行为方式与大多数其它子命令不同。
当我启动Apache,mod_dav_svn抱怨说发现一个“bad database version”,它发现了db-3.X而不是db-4.X。
我在RedHat 9得到“Function not implemented”错误,无法工作,我如何修正这个问题?
为什么日志说通过Apache(ra_dav)提交或导入的文件“(no author)”?
我偶然在Windows得到“Access Denied”错误,它们看起来随即出现。
在FreeBSD,某些操作(特别是svnadmin create)有时会挂起。
我可以在web浏览器看到我的版本库,但是svn checkout给我一个301 Moved Permanently错误。
我尝试察看我的文件的一个老版本,但是svn告诉我“path not found”。
C. WebDAV和自动版本化
WebDAV基本概念
仅是平常的WebDAV
DeltaV扩展
Subversion和DeltaV
影射Subversion到DeltaV
自动版本化支持
选择mod_dav_lock
自动版本化交互性
Win32网络文件夹
Mac OS X
Unix: Nautilus 2
Linux davfs2
D. 第三方工具
客户端和插件
语言绑定
版本库转化
高级工具
版本库浏览工具
E. 版权
术语表

插图清单

1.1. Subversion的架构
2.1. 一个典型的客户/服务器系统
2.2. 需要避免的问题
2.3. 锁定-修改-解锁 方案
2.4. 拷贝-修改-合并 方案
2.5. 拷贝-修改-合并 方案(续)
2.6. 版本库的文件系统
2.7. 版本库
4.1. 分支开发
4.2. 开始规划版本库
4.3. 拷贝后的版本库
4.4. 一个文件的分支历史
8.1. 二维的文件目录
8.2. 版本时间—第三维!

表格清单

2.1. 版本库访问URL
5.1. 版本库数据存储对照表
6.1. 网络服务器比较
8.1. Subversion库的摘要目录

范例清单

5.1. 使用svnshell浏览版本库
5.2. txn-info.sh(异常事务报告)
6.1. 匿名访问的配置实例。
6.2. 一个认证访问的配置实例。
6.3. 一个混合认证/匿名访问的配置实例。
6.4. 关闭所有的路经检查
7.1. 注册表条目(.reg)样本文件。
8.1. 使用版本库层
8.2. 使用Python处理版本库层
8.3. 一段检出工作拷贝的简单脚本
8.4. 典型的.svn/entries文件内容
8.5. 有效地池使用 

译者序

最早接触这本书是在2004上半年,当时Subversion 1.0刚刚发布,而我很快把它引入到我们的项目当中,相对于CVS的简陋,Subversion显得非常的完备,是一个经过了深思熟虑的产品,是新一代开源项目的代表。

当我看到这本免费共享的图书,注意到了它已经在O‘Reilly出版,而网站上有最新的版本可以下载,对于这种开源文化赞叹不已,萌生了自己翻译这本书的想法,但是苦于当时对DocBook非常不熟悉,于是使用文本格式,利用闲暇时间翻译了前四章,但后来杂事渐多,竟然慢慢忘了此事。

一转眼到了2005年,Subversion 1.2发布了,我的注意力又转到了这个领域,正好我有了做一个网站的念头,所以就有了Subversion中文站(http://www.subversion.org.cn),而同时我也开始申请成为这本书的中文官方翻译。

这本书的官方翻译要求我必须使用DocBook,要求我必须有一个团队,于是我在这两方面进行了努力,于是有人开始与我并肩工作了。在这段翻译的时间里陆续有人加入进来,按照时间顺序是rocksun、jerry、nashwang、gxio、MichaelDuan、viv、lifengliu2000、genedna、luyongshou、leasun和nannan。但是必须要说明这不是对翻译贡献大小的排序,大家都在自己的能力范围内为这个翻译做出了自己的贡献,感谢我们成员的努力,也感谢许多对我们提出建议的朋友。

开始的时候并没有觉得做好这件事有多难,但当看到翻译的东西自己都读不懂的时候,我感到了一种压力。如果这翻译还不如英文,我们还有没有必要继续。好在在大家的支持下,我越来越喜欢这本书了,渐渐的发现自己可以把这本书当作自己的参考材料了。

但是,我也有过许多疑惑,在中国人们似乎只是把版本控制工具当做一个代码分享的工具,而没有把它融入到整个软件开发的生命周期当中,这也难怪,大多数中国软件的寿命似乎并不长,不需要那么多复杂的配置管理。所以我们的这些翻译能够给大家带来多大的帮助要由中国软件的发展决定,希望我们的工作能够伴随着中国软件的腾飞不断成长。

让我们一起努力吧! 前言

一个不太好的常见问题列表(FAQ),常常并不是由人们实际上的问题组成,而经常是由作者期待的问题组成。或许你曾经见过这种类型的问题:

Q:怎样使用Glorbosoft XYZ提高生产率?

A:许多客户希望知道怎样通过革新我们特许的办公室群件来提高生产率,回答非常简单:首先点击“文件” 菜单,鼠标移到“提高生产率”,然后…

这样的FAQ并不是其字面意义上的FAQ,没有人会这样询问支持者,“怎样提高生产率?”相反,人们经常询问一些更具体的问题,像“怎样修改日程系统提前两天而不是提前一天去提醒被提醒人?”等等。但是通过想象比去发现一个这样的问题列表更容易,编辑一个真实的问题列表需要持续的,有组织的工作,覆盖软件的整个生命周期,提出的问题必须被追踪,要监控反馈,所有问题要收集为一个一致的,可查询的整体,并且能够反映所有用户的经验。这需要耐心,像实地博物学家一样严谨的态度,不应该有浮华的假设,虚幻的断言—而需要开放的视野和精确的记录。

之所以会喜欢这本书,是因为这本书非凡的成长过程,这体现在每一页里,这是作者与用户直接交流的结果。这一切的基础是Ben Collins-Sussman‘s关于Subversion常见问题邮件列表的研究:使用subversion通常的流程是怎样的?分支与标签同其它版本控制系统的工作方式是一样的吗?我怎样知道某一处修改是谁做的?

由于每天看到相同问题的失落,Ben在2002年夏天努力工作了一个月,撰写了一本Subversion手册,一本六十页,涵盖了所有基础使用知识的手册。这本手册没有说明什么时候要结束,伴随着Subversion的版本,帮助用户开始最初的学习。当O‘Reilly决定出版一本完备的Subversion图书的时候,最快捷的方式很明显,就是扩充这本书。

三个联合作者因而面临了一个不寻常的机会。从职责上讲,他们的任务是以一些原始内容为基础,从头到尾写一个草稿。但实际上他们正在使用着一些丰富的自下而上的原材料,像一条稳定的河流,也可能是一口不可预料的间歇泉。Subversion被数以千计的用户采用,这些用户提供了大量的反馈,不仅仅针对Subversion,还包括业已存在的文档。

在写这本书的过程里,Ben,Mike 和 Brian想鬼魂一样一直游荡在Subversion邮件列表和聊天室中,仔细的研究用户实际遇到的问题。监视这些反馈是他们在CollabNet工作的一部分,这给他们开始写这本书时提供了巨大的便利。这本书建立在丰富经验的根基之上,并不是在流沙一样的想象之上;它结合了用户手册和FAQ最好的一面,在第一次阅读时,这种二元性并不明显,按照顺序,从前到后,这本书只是简单的从头到尾的关于软件细节的描述。有一个总的看法,有一个教程,有一章关于管理配置,还有一些高级主题,当然也有一个命令参考和故障指南。只有当你过一段时间之后,返回来找一些特定问题的解决方案时,这种二元性才得以显现:这些生动的细节一定来自不可预料的实际用例的提炼,大多是源于用户的需要和视点。

当然,没人可以承诺这本书可以回答所有问题。尽管有时候一些前人提问的惊人一致性让你感觉是心灵感应;你仍有可能在社区的知识库里摔跤,空手而归。如果有这种情况,最好的办法是写明问题发送email到,作者还在那里关注着社区,不仅仅封面提到的三位,还包括许多曾经作出修正与提供原始材料的人。从社区的视角,帮你解决问题只是逐步的调整这本书,进一步调整Subversion本身以更合理的适合用户使用这样一个大工程的一个有趣的额外效用。他们渴望你的信息,不仅仅可以帮助你,也因为可以帮助他们。与Subversion这样活跃的自由软件项目一起,你并不孤单

让这本书将成为你的第一个伙伴。 序言

目录

读者
怎样阅读本书
本书约定
排版习惯
图标
本书组织结构
Subversion 1.1的新特性
这本书是免费的
致谢
来自Ben Collins-Sussman
来自Brian W. Fitzpatrick
来自C. Michael Pilato

“如果C给你足够的绳子吊死你自己,试着用Subversion作为一种存放绳子的工具。” —Brian W. Fitzpatrick

在开源软件领域,并行版本系统(CVS)一直是版本控制的选择。恰如其分的是,CVS本身是一个自由软件,它的非限制性的技法和对网络操作的支持—允许大量的不同地域分散的程序员可以共享他们工作的特性—非常符合开源软件领域合作的精神,CVS和它半混乱状态的开发模型成为了开源文化的基石。

但是像许多其他工具一样,CVS开始显露出衰老的迹象。Subversion是一个被设计成为CVS继任者的新版本控制系统。设计者通过两个办法来争取现有的CVS用户: 使用它构建一个开源软件系统的版本控制过程,从感觉和体验上与CVS类似,同时Subversion努力弥补CVS许多明显的缺陷,结果就是不需要版本控制系统一个大的革新。Subversion是非常强大、有用及灵活的工具。

这本书是为Subversion 1.1 系列撰写的,我们试图涵盖Subversion的所有内容,但是Subversion有一个兴盛和充满活力的开发社区,已经有许多特性和改进计划在新的版本中实现,可能会与目前这本书中的命令与细节不一致。

读者

这本书是为了那些希望使用Subversion管理他们数据的在计算机领域有丰富知识的人士准备的。Subversion可以在多种不同的操作系统上运行,它的主要用户操作界面是基于命令行的,这就是我们将要在本书中提到的命令行工具(svn)。出于一致性,本书的例子假定读者使用的是类Unix的操作系统,并且熟悉Unix和命令行界面。

那就是说,svn程序可以运行在像Microsoft Windows这样的非Unix平台上。除了一些微小的不同,像用反斜线(\)代替正斜线(/)作为路径分隔符,在Windows上运行svn工具进行输入输出和Unix平台上的功能是完全一致的。Windows用户甚至可以发现这个程序能够在Unix仿真环境Cygwin中成功运行。

大多数读者可能是那些需要跟踪代码变化的程序员或者系统管理员。这是Subversion最普通的用途,因此这个场景贯穿于整本书的例子。但是Subversion能够被用来管理任何类型的数据:图像、音乐、数据库、文档等等。对于Subversion,所有的数据仅仅是数据而已。

这本书假定读者从来没有使用过任何版本控制系统,我们也努力使CVS用户能够轻而易举的跳跃到Subversion中。偶尔一些特殊的工具条可能讨论CVS,在最后一个特别的附录中将总结Subversion和CVS的不同。 

怎样阅读本书

这本书的目标读者非常的广泛—从从未使用过版本控制的新手到经验丰富的系统管理员。根据你的基础,特定的章节可能对你更有用,下面的内容可以看作是为各类用户提供的“推荐阅读清单”:

资深管理员

假设你以前已经使用过CVS,希望得到一个Subversion服务器并且尽快运行起来,第5、6章将会告诉你怎样建立第一个版本库,并且使之在网络上可用,此后,根据你的CVS使用经验,第3章和附录A告诉你怎样使用Subversion客户端。

新用户

你的管理员已经为你准备好了Subversion服务,你将学习如何使用客户端。如果你没有使用过版本控制系统(像CVS),那么第2、3章是重要的介绍,如果你是CVS的老手,最好从第3章和附录A开始。

高级用户

无论你只是个使用者还是管理员,最终你的项目会长大,你想通过Subversion作许多高级的事情,像如何使用分支和执行合并(第4章),怎样使用Subversion的属性支持,怎样配制运行参数(第7章)等等。第4、7章一开始并不重要,但你适应了基本操作之后一定要读一下。

开发者

大概你已经很熟悉Subversion了,你想扩展它并在它的API基础之上开发新软件,第8章将是为你准备的。

这本书以一个参考材料作为结束—第9章包括了所有命令的参考,这个附录包括了许多有用的主题,当你完成了本书的阅读,你会经常去看这个章节。

本书约定

这一部分包括书中各种约定。

排版习惯

等宽

用在命令,命令输出和转换

等宽斜体

用在代码和文本中可替换的部分

斜体

用在文件和路径名

图标


注意这些源代码只是—例子,需要通过正确编译咒语进行编译,它们只是为了描述在手边的问题,没有必要注意好的编码样式。

本书组织结构

以下是章节和其中的内容介绍:

第1章,介绍

记述了Subversion的历史与特性、架构、组件和安装方法,还包括一个快速入门指南。

第2章,基本概念

解释了版本控制的基础知识,介绍了不同的版本模型,随同讲述了Subversion的版本库,工作拷贝和修订版本的概念。

第3章,指导教程

带领你作为一个Subversion用户开始工作,示范了怎样使用Subversion获得、修改和提交数据。

第4章,分支和合并

讨论分支、合并与标签,包括一个最佳实践,通常的用例,怎样取消修改,以及怎样从一个分支转到另一个分支。

第5章,版本库管理

讲述Subversion版本库的基本概念,怎样建立、配置和维护版本库,以及你可以使用的工具。

第6章,配置服务器

解释了怎样配置Subversion服务器,以及三种访问版本库的方式,HTTPsvn协议和本地访问。这里也介绍了认证的细节,以及授权与匿名访问方式。

第7章,高级主题

研究Subversion客户配置文件,文件和目录属性,怎样忽略工作拷贝中的文件,怎样引入外部版本树到工作拷贝,最后介绍了如何掌握卖主分支。

第8章,开发者信息

介绍了Subversion的核心,Subversion文件系统,以及从程序员的角度如何看待工作拷贝的管理区域,介绍了如何使用公共APIs写程序使用Subversion,最重要的是,怎样投身到Subversion的开发当中去。

第9章,Subversion完全手册

深入研究研究所有的命令,包括 svnsvnadmin、和svnlook以及大量的相关实例

附录A,Subversion对于CVS用户

比较Subversion与CVS的异同点,消除多年使用CVS养出的坏习惯的建议,包括subversion版本号、标记版本的目录、离线操作、updatestatus、分支、标签、元数据、冲突和认证。

附录B,故障解决

叙述常见的问题,以及使用和编译Subversion的难点。

附录C,WebDAV与自动版本化

描述了WebDAV与DeltaV的细节,和怎样将你的Subversion版本库作为可读/写的DAV共享装载。

附录D,第三方工具

讨论一些支持和使用Subversion的工具,包括可选的客户端工具,版本库浏览工具等等。

Subversion 1.1的新特性

本版图书覆盖了Subversion 1.1的新特性,下面是一个1.1主要变化的列表。

非数据库的版本库

现在可以创建不使用Berkeley DB数据库的版本库,作为替代,这个新的版本库使用普通的文件系统,使用自定义的文件格式,这个版本库不是一个脆弱的“楔入”,它和Berkeley DB版本库一样经过很好的测试,见“版本库数据存储”一节。

对象链接纳入版本控制

Unix用户可以创建一个对象链接,使用svn add放置到版本控制,见svn add和“svn:special”一节。

客户可以追踪拷贝和改名

文件和目录的分支(拷贝)维护着他们与历史的联系,但是在Subversion 1.0中svn log追踪历史的方式与svn diffsvn mergesvn listsvn cat都不同,在Subversion 1.1,所有的客户端子命令可以透明的回溯到拷贝和改名之前的历史文件和目录。

客户端自动转化URI和IRI

在1.0的命令行客户端,用户需要手工的回避URL,客户端只能接收“合法正确的”URL,例如http://host/path%20with%20space/project/espa%F1a。1.1命令行客户端现在知道了web浏览器长久以来所做的事情:它会自动回避用户在shell放置的空格和重音字符之类的字符:"http://host/path with space/project/españa"

本地化的用户信息

Subversion 1.1现在使用gettext()来为用户显示翻译的错误信息和帮助消息。现在有的翻译包括德国、西班牙、波兰、瑞典、繁体中文、日本、巴西、葡萄牙和挪威Bokmal,为了本地化你的Subversion客户端,只需要设置你的shell的LANG环境变量为支持的某个值(例如de_DE)。

可分享的工作拷贝

允许多个用户分享一个工作拷贝有一些历史问题,现在相信已经修正了。

store-passwords运行变量

这是一个新的运行变量用来关闭密码缓存,所以服务器证书可以缓存,见“config”一节。

优化和bug修正

svn checkoutsvn updatesvn statussvn blame会更快,超过50个小bug被修正,都在项目的CHANGES文件(在http://svn.collab.net/repos/svn/trunk/CHANGES )里描述。

新的命令选项
  • svn blame --verbose:见 svn blame.

  • svn export --native-eol EOL:见 svn export.

  • svn add --force:见 svn add.

  • svnadmin dump --deltas:见 “版本库的移植”一节.

  • svnadmin create --fs-type TYPE:见 svnadmin create.

  • svnadmin recover --wait:见 svnadmin recover.

  • svnserve --tunnel-user=NAME:见 “svnserve选项”一节.

这本书是免费的

这本书是作为Subversion项目的文档,由开发者开始撰写的,后来成为一个独立工作并进行了重写,因此,它一直有一个免费许可证(见附录 E, 版权。)实际上,这本书是在公众关注中写出来的,作为Subversion的一部分,它有两种含义:

  • 你一直可以在Subversion的版本库里找到本书的最新版本。

  • 对于这本书,你可以任意分发或者修改—它是免费许可证,当然,相对于发布你的私有版本,你最好向Subversion开发社区提供反馈。为了能够参与到社区,见“为Subversion做贡献”一节来学习如何加入到社区。

你可以向O‘Reilly发布评论和问题:###insert boilerplate.

一个相对新的在线版本可以在http://svnbook.red-bean.com找到。

致谢

没有Subversion就没有可能(或者有用)有这本书,所以作者很乐意去感谢Brian Behlendorf和CollabNet,有眼光开始这样一个冒险和野心勃勃的开源项目;Jim Blandy给了Subversion这个名字和最初的设计—我们爱你。还有Karl Fogel,伟大社区领导和好朋友。 [1]

感谢O‘Reilly和我们的编辑Linda Mui和Tatiana对我们的耐心的支持。

最后,我们要感谢数不清的曾经为社区作出贡献的人们,他们提供了非正式的审计、建议和修正:这一定不是一个最终的完整列表,离开了这些人的帮助,这本书不会这样完整和正确:Jani Averbach, Ryan Barrett, Francois Beausoleil, Jennifer Bevan, Matt Blais, Zack Brown, Martin Buchholz, Brane Cibej, John R. Daily, Peter Davis, Olivier Davy, Robert P. J. Day, Mo DeJong, Brian Denny, Joe Drew, Nick Duffek, Ben Elliston, Justin Erenkrantz, Shlomi Fish, Julian Foad, Chris Foote, Martin Furter, Dave Gilbert, Eric Gillespie, Matthew Gregan, Art Haas, Greg Hudson, Alexis Huxley, Jens B. Jorgensen, Tez Kamihira, David Kimdon, Mark Benedetto King, Andreas J. Koenig, Nuutti Kotivuori, Matt Kraai, Scott Lamb, Vincent Lefevre, Morten Ludvigsen, Paul Lussier, Bruce A. Mah, Philip Martin, Feliciano Matias, Patrick Mayweg, Gareth McCaughan, Jon Middleton, Tim Moloney, Mats Nilsson, Joe Orton, Amy Lyn Pilato, Kevin Pilch-Bisson, Dmitriy Popkov, Michael Price, Mark Proctor, Steffen Prohaska, Daniel Rall, Tobias Ringstrom, Garrett Rooney, Joel Rosdahl, Christian Sauer, Larry Shatzer, Russell Steicke, Sander Striker, Erik Sjoelund, Johan Sundstroem, John Szakmeister, Mason Thomas, Eric Wadsworth, Colin Watson, Alex Waugh, Chad Whitacre, Josef Wolf, Blair Zajac, 以及整个Subversion社区。

来自Ben Collins-Sussman

感谢我的妻子Frances,在几个月里,我一直在对你说,“但是亲爱的,我还在为这本书工作”,非比寻常,“但是亲爱的,我还在处理邮件”。我不知道她为什么会如此耐心!她是我完美的平衡点。

感谢我的家人对我的鼓励,无论是否对我的题目感兴趣。(你知道的,一个人说 “哇,你正在写一本书?”,然后当他知道你是写一本计算机书时,那种惊讶就变得没有那么多了。)

感谢我身边让我富有的朋友,不要那样看我—你们知道你们是谁。

来自Brian W. Fitzpatrick

非常非常感谢我的妻子Marie的理解,支持和最重要的耐心。感谢引导我学会UNIX编程的兄弟Eric,感谢我的母亲和外祖母的支持,对我在圣诞夜里埋头工作的理解。

Mike和Ben:与你们一起工作非常快乐,Heck,我们在一起工作很愉快!

感谢所有在Subversion和Apache软件基金会的人们给我机会与你们在一起,没有一天我不从你们那里学到知识。

最后,感谢我的祖父,他一直跟我说“自由等于责任”,我深信不疑。

来自C. Michael Pilato

特别感谢我的妻子Amy,由于她的耐心照顾,由于她对我熬夜的容忍,由于她用难以想象的优雅方式修订我的每一个章节—你总能先行一步。Gavin,你已经大到可以阅读了,我希望你能为我这样一个爸爸感到骄傲,像我为你骄傲一样。爸爸妈妈(家庭的其余部分),感谢你们恒久不变的支持和鼓励。

向你们致敬,Shep Kendall,为我打开了计算机世界的大门;Ben Collins Sussman,我在开源世界的导师;Karl Fogel—你我的.emacs;Greg Stain,让我在困境中知道怎样编程;Brain Fitzpatrick—同我分享他的写作经验。所有我曾经从你们那里获得知识的人—尽管又不断忘记。

最后,对所有为我展现完美卓越创造力的人们—感谢。

第 1 章 介绍

目录

Subversion是什么?
Subversion的历史
Subversion的特性
Subversion的架构
安装Subversion
Subversion的组件
快速入门

版本控制是管理信息变化的艺术,它很早就成为了程序员重要的工具,程序员经常会花时间做一点小修改然后第二天又把它改回来。但是版本控制的作用不仅在软件开发领域,任何需要管理频繁信息改变的地方都需要它,这就是Subversion发挥的舞台。

这一章是一个对Subversion高层次的介绍—它是什么;它能做什么;它是怎样做到的。

Subversion是什么?

Subversion是一个自由/开源版本控制系统,它管理文件和目录可以超越时间。一组文件存放在中心版本库,这个版本库很像一个普通的文件服务器,只是它可以记录每一次文件和目录的修改,这便使你可以取得数据以前的版本,从而可以检查所作的更改。从这个方面看,许多人把版本控制系统当作一种“时间机器”。

Subversion可以通过网络访问它的版本库,从而使用户可以在不同的电脑上使用。一定程度上可以说,允许用户在各自的地方修改同一份数据是促进协作。进展可能非常的迅速,并没有一个所有的改变都会取得效果的通道,由于所有的工作都有历史版本,你不必担心由于失去某个通道而影响质量,如果存在不正确的改变,只要取消改变。

一些版本控制系统也是软件配置管理(SCM)系统,这种系统经过特定的精巧设计来管理源代码,有许多关于软件开发的特性—本身理解编程语言、或者提供构建程序的工具。然而,Subversion不是这样一个系统,它是一个通用系统,可以管理任何类型的文件集,对你这可能是源代码—对别人,可能是一个货物清单或者是数字电影。

Subversion的历史

早在2000年,CollabNet, Inc. (http://www.collab.net) 开始寻找CVS替代产品的开发人员,CollabNet提供了一个协作软件套件SourceCast,它的一个组件是版本控制系统。尽管SourceCast在初始时使用CVS作为其版本控制系统,但是CVS的局限性在一开始就很明显,CollabNet知道迟早要找到一个更好的替代品。遗憾的是,CVS成为了开源世界事实上的标准,因为没有更好的产品,至少是没有可以自由使用的。所以CollabNet决定写一个新的版本控制系统,建立在CVS思想之上的,但是修正其错误和不合理的特性。

2000年2月,他们联系Open Source Development with CVS(Coriolis, 1999)的作者Karl Fogel,并且询问他是否希望为这个新项目工作,巧合的是,当时Karl正在与朋友Jim Blandy讨论设计一个新的版本控制系统。在1995年,他们两个曾经开办一个提供CVS支持的公司Cyclic Software,尽管他们最终卖掉了公司,但还是天天使用CVS进行日常工作,在使用CVS时的挫折最终促使他们认真地去考虑如何管理标记版本的数据,而且他们当时不仅仅提出了“Subversion”这个名字,并且做出了Subversion版本库的基础设计。所以当CollabNet提出邀请的时候,Karl马上同意为这个项目工作,同时Jim也得到了他的雇主,RedHat软件赞助他到这个项目并提供了一个宽松的时间。CollabNet雇佣了Karl和Ben Collins Sussman,详细的设计从三月开始,在Behlendorf 、CollabNet、Jason Robbins 和 Greg Stein(当时是一个独立开发者,活跃在WebDAV/DeltaV系统规范阶段)的恰当激励的帮助下,Subversion很快吸引了许多活跃的开发者,结果是许多有CVS经验的人们很乐于有机会为这个项目做些事情。

最初的设计小组固定在简单的目标上,他们不想在版本控制方法学中开垦处女地,他们只是希望修正CVS,他们决定Subversion匹配CVS的特性,保留相同的开发模型,但不复制CVS明显的缺陷。尽管它不需要成为CVS的继任者,它也应该与CVS保持足够的相似性,使得CVS用户可以轻松的做出转换。

经过14个月的编码,2001年8月31日,Subversion自己能够“成为服务”了,开发者停止使用CVS保存Subversion的代码,而使用Subversion本身。

当CollabNet开始这个项目的时候,曾经资助了大量的工作(它为全职的Subversion开发者提供薪水),Subversion像许多开源项目一样,被一些激励知识界精英的宽松透明的规则支配着。CollabNet的版权许可证完全符合Debian的自由软件方针,也就是说,任何人可以自由的下载,修改和重新发布,不需要经过CollabNet或其他人的允许。

Subversion的特性

当讨论Subversion为版本控制领域带来的特性的时候,通过学习它在CVS基础上所作的改进会是比较有效的方法。如果你不熟悉CVS,你会不太明白所有的特性,如果你根本就不熟悉版本控制,你会瞪着眼无所适从,你最好首先阅读一下第 2 章 基本概念,它提供了一个版本控制的简单介绍。

Subversion提供:

版本化的目录

CVS只记录单个文件的历史,但是Subversion实现了一个可以跟踪目录树更改的“虚拟”版本化文件系统,文件目录都是有版本的。

真实的版本历史

因为CVS只记录单个文件的版本,对于拷贝和改名—这些文件经常发生的操作,会改变一个目录的内容—在CVS中并不支持。在CVS里你也不可以用一个完全不同的文件覆盖原来的同名文件而又不继承原来文件的历史。通过Subversion,你可以对文件或是目录进行增加、拷贝和改名操作,也可以新增一个具有干净历史的文件。

原子提交

一系列的改动,要么全部提交到版本库,要么一个也不提交,这样可以让用户构建一个所要提交修改的逻辑块,防止部分修改提交到版本库。

版本化的元数据

每一个文件或目录都有一套属性—键和它们的值,你可以建立并存储任何键/值对,属性也是随时间的流逝而纳入版本控制的,很像文件的内容。

可选的网络层

Subversion在版本库访问方面有一个抽象概念,利于人们去实现新的网络机制,Subversion可以作为一个扩展模块与Apache结合,这给了Subversion在稳定性和交互性方面很大的好处,可以直接使用服务器的特性—认证、授权和传输压缩等等。也有一个轻型的,单独运行的Subversion服务,这个服务使用自己的协议可以轻松的用SSH封装。

一致的数据操作

Subversion表示文件是建立在二进制文件区别算法基础上的,对于文本(可读)和二进制(不可读)文件具备一致的操作方式,两种类型的文件都压缩存放在版本库中,区别信息是在网络上双向传递的。

有效率的分支和标签

分支与标签的代价不与工程的大小成比例,Subversion建立分支与标签时只是拷贝整个工程,使用了一种类似于硬链接的机制,因而这类操作通常只会花费很少并且相对固定的时间。

可修改性

Subversion没有历史负担,它由一系列良好的共享C库实现,具有定义良好的API,这使得Subversion非常容易维护,可以轻易的用其他语言操作。

Subversion的架构

图 1.1 “Subversion的架构”从高处“俯视”Subersion的设计。

图 1.1. Subversion的架构

一端是保存你所有纳入版本控制的数据的Subversion版本库,在另一端是你的Subvesion客户端程序,管理着所有纳入版本控制数据的本地影射(叫做“工作拷贝”),在这两极之间是各种各样的版本库访问(RA)层,一些使用电脑网络通过网络服务器访问版本库,一些则绕过网络服务器直接访问版本库。

安装Subversion

Subversion建立在一个可移植层上,叫做APR(Apache Portable Runtime library),这意味着Subversion可以在所有可运行Apache服务器的平台上工作:Windows、Linux、各种BSD、Mac OS X、Netware以及其他。

最简单的安装办法就是下载相应操作系统的二进制包,Subversion的网站(http://subversion.tigris.org)上通常会有志愿者提供的包可以下载,对于微软操作系统,网站上通常会有图形化的安装包,对于类Unix系统,你可以使用它们本身的打包系统(PRMs、DEBs、ports tree等等)得到Subversion。

你也可以选择从源代码直接编译Subversion,从网站下载最新的源代码,解压缩,根据INSTALL文件的指导进行编译。注意,通过这些源代码可以完全编译访问服务器的命令行客户端工具(通常是apr,apr-util和neno库)。但是可选部分有许多依赖,如Berkeley DB和Apache httpd。如果你希望做一个完全的编译,确定你有所有INSTALL文件中记述的包。如果你计划通过Subversiong本身工作,你可以使用客户端程序取得最新的,带血的源代码,这部分内容见“取得源代码”一节。

Subversion的组件

Subversion安装之后,分为几个部分,这是一个快速浏览。不要害怕这些让你挠头的简略描述,本书有足够的内容来减少这种混乱。

svn

命令行客户端。

svnversion

报告工作拷贝状态(当前修订版本的项目)的工具。

svnlook

检查版本库的工具。

svnadmin

建立、调整和修补版本库的工具。

svndumpfilter

过滤Subversion版本库转储文件的工具。

mod_dav_svn

Apache HTTP服务器的一个插件,可以让版本库在网络上可见。

svnserve

一种单独运行的服务器,可以作为守护进程由SSH调用,另一种让版本库在网络上可见的方式。

假定你已经将Subversion正确安装,你已经准备好开始,下两章将带领你使用svn,Subversion的客户端程序。

快速入门

许多人为“从头到尾”的方式读一本介绍有趣新技术的书感到发愁,这一小节是一个很短的介绍,给许多“实用”的用户一个实战的机会,如果你是一个喜欢通过实验进行学习的用户,以下将告诉你怎么做,相对应,我们给出这本书相关的链接。

如果版本控制或者Subversion和CVS都用到的“拷贝-修改-合并”模型对于你来说是完全的新概念,在进一步阅读之前,你首先要读第 2 章 基本概念

注意

以下的例子假定你有了svn这个客户端程序,也有svnadmin这个管理程序,你的svn也应该在Berkeley DB的基础上进行编译。为了验证这些,运行svn --version,确定ra_local模块存在,如果没有,这个程序不能访问file://的URL。

Subversion存储所有版本控制的数据到一个中心版本库,作为开始,新建一个版本库:

$ svnadmin create /path/to/repos$ ls /path/to/reposconf/  dav/  db/  format  hooks/  locks/  README.txt

这个命令建立了一个新的目录 /path/to/repos,包含了一个Subversion版本库。确定这个目录在本地磁盘上,而不是一个网络共享,这个新的目录保存着一些Berkeley DB的数据库文件,你打开后看不到你的已经版本化的文件。更多的版本库创建和维护信息,见第5章第 5 章 版本库管理

第二步,建立一些将要导入到版本库的文件与目录,为了以后使用更清楚(见第 4 章 分支与合并),你的文件应该包括三个顶级子目录,分别是branchestagstrunk

/tmp/project/branches//tmp/project/tags//tmp/project/trunk/foo.cbar.cMakefile…

一旦你有了树形结构和数据你就可以继续了,使用svn import导入数据到版本库(见“svn import”一节部分):

$ svn import /tmp/project file:///path/to/repos -m "initial import"Adding         /tmp/project/branchesAdding         /tmp/project/tagsAdding         /tmp/project/trunkAdding         /tmp/project/trunk/foo.cAdding         /tmp/project/trunk/bar.cAdding         /tmp/project/trunk/Makefile…Committed revision 1.$

现在版本库已经包含你的目录和数据了,注意原先的/tmp/project目录没有任何变化;Subversion不管这个,(事实上,你甚至可以任意删除这个目录)。为了处理 版本库的数据,你需要创建一个新的包含数据的“工作拷贝”,一个私人的工作空间。告诉Subversion来“取出”版本库的trunk目录:

$ svn checkout file:///path/to/repos/trunk projectA  project/foo.cA  project/bar.cA  project/Makefile…Checked out revision 1.

你现在在project目录里有了一个版本库的个人拷贝,你可以编辑你的工作备份中的文件,并且提交到版本库。

  • 进入到你的工作备份,编辑一个文件的内容。

  • 运行svn diff来查看你的修改的标准区别输出。

  • 运行svn commit来提交你的改变到版本库。

  • 运行svn update将你的工作拷贝与版本库“同步”。

对于你对工作拷贝可做操作的完全教程可以察看第 3 章 指导教程

目前,你可以选择使你的版本库在网络上可见,可以参考第 6 章 配置服务器,学习使用不同的服务器以及配置。

第 2 章 基本概念

目录

版本库
版本模型
文件共享的问题
锁定-修改-解锁 方案
拷贝-修改-合并 方案
Subversion实战
工作拷贝
修订版本
工作拷贝怎样追踪版本库
修订版本混合的限制
摘要

这一章是对Subversion一个简短和随意的介绍,如果你对版本控制很陌生,这一章节完全为你准备的,我们从讨论基本概念开始,深入理解Subversion的思想,然后展示许多简单的实例。

尽管我们的例子展示了人们如何分享程序源代码,仍然要记住Subversion可以控制所有类型的文件—它并没有限制在只为程序员工作。

版本库

Subversion是一种集中的分享信息的系统,它的核心是版本库,它储存所有的数据,版本库按照文件树形式储存数据—包括文件和目录。任意数量的客户端可以连接到版本库,读写这些文件。通过写,别人可以看到这些信息,通过读数据,可以看到别人的修改。图 2.1 “一个典型的客户/服务器系统”描述了这种关系:

图 2.1. 一个典型的客户/服务器系统

所以为什么这很有趣呢?讲了这么多,让人感觉这是一种普通的文件服务器,但实际上,版本库另一种文件服务器,而不是你常见的那一种。最特别的是Subversion会记录每一次的更改,不仅针对文件也包括目录本身,包括增加、删除和重新组织文件和目录。

当一个客户端从版本库读取数据时,通常只会看到最新的版本,但是客户端也可以去看以前的任何一个版本。举个例子,一个客户端可以发出这样的历史问题“上个星期三的目录是怎样的?”或是“谁最后一个更改了这个文件,更改了什么?”,这些是每一种版本控制系统的核心问题:系统是设计来记录和跟踪每一次改动的。

版本模型

版本控制系统的核心任务是提供协作编辑和数据共享,但是不同的系统使用不同的策略来达到目的。

文件共享的问题

所有的版本控制系统都需要解决这样一个基础问题:怎样让系统允许用户共享信息,而不会让他们因意外而互相干扰?版本库里意外覆盖别人的更改非常的容易。

考虑图 2.2 “需要避免的问题”的情景,我们有两个共同工作者,Harry和Sally,他们想同时编辑版本库里的同一个文件,如果首先Harry保存它的修改,过了一会,Sally可能凑巧用自己的版本覆盖了这些文件,Harry的更改不会永远消失(因为系统记录了每次修改),Harry所有的修改不会出现在Sally的文件中,所以Harry的工作还是丢失了—至少是从最新的版本中丢失了—而且是意外的,这就是我们要明确避免的情况!

图 2.2. 需要避免的问题

锁定-修改-解锁 方案

许多版本控制系统使用锁定-修改-解锁这种机制解决这种问题,在这样的系统里,在一个时间段里版本库的一个文件只允许被一个人修改。首先在修改之前,Harry要“锁定”住这个文件,锁定很像是从图书馆借一本书,如果Harry锁住这个文件,Sally不能做任何修改,如果Sally想请求得到一个锁,版本库会拒绝这个请求。在Harry结束编辑并且放开这个锁之前,她只可以阅读文件。Harry解锁后,就要换班了,Sally得到自己的轮换位置,锁定并且开始编辑这个文件。图 2.3 “锁定-修改-解锁 方案”描述了这样的解决方案。

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

锁定-修改-解锁模型有一点问题就是限制太多,经常会成为用户的障碍:

  • 锁定可能导致管理问题。有时候Harry会锁住文件然后忘了此事,这就是说Sally一直等待解锁来编辑这些文件,她在这里僵住了。然后Harry去旅行了,现在Sally只好去找管理员放开锁,这种情况会导致不必要的耽搁和时间浪费。

  • 锁定可能导致不必要的线性化开发。如果Harry编辑一个文件的开始,Sally想编辑同一个文件的结尾,这种修改不会冲突,设想修改可以正确的合并到一起,他们可以轻松的并行工作而没有太多的坏处,没有必要让他们轮流工作。

  • 锁定可能导致错误的安全状态。假设Harry锁定和编辑一个文件A,同时Sally锁定并编辑文件B,如果A和B互相依赖,这种变化是必须同时作的,这样A和B不能正确的工作了,锁定机制对防止此类问题将无能为力—从而产生了一种处于安全状态的假相。很容易想象Harry和Sally都以为自己锁住了文件,而且从一个安全,孤立的情况开始工作,因而没有尽早发现他们不匹配的修改。

拷贝-修改-合并 方案

Subversion,CVS和一些版本控制系统使用拷贝-修改-合并模型,在这种模型里,每一个客户联系项目版本库建立一个个人工作拷贝—版本库中文件和目录的本地映射。用户并行工作,修改各自的工作拷贝,最终,各个私有的拷贝合并在一起,成为最终的版本,这种系统通常可以辅助合并操作,但是最终要靠人工去确定正误。

这是一个例子,Harry和Sally为同一个项目各自建立了一个工作拷贝,工作是并行的,修改了同一个文件A,Sally首先保存修改到版本库,当Harry想去提交修改的时候,版本库提示文件A已经过期,换句话说,A在他上次更新之后已经更改了,所以当他通过客户端请求合并版本库和他的工作拷贝之后,碰巧Sally的修改和他的不冲突,所以一旦他把所有的修改集成到一起,他可以将工作拷贝保存到版本库,图 2.4 “拷贝-修改-合并 方案”和图 2.5 “拷贝-修改-合并 方案(续)”展示了这一过程。

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

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

但是如果Sally和Harry的修改交迭了该怎么办?这种情况叫做冲突,这通常不是个大问题,当Harry告诉他的客户端去合并版本库的最新修改到自己的工作拷贝时,他的文件A就会处于冲突状态:他可以看到一对冲突的修改集,并手工的选择保留一组修改。需要注意的是软件不能自动的解决冲突,只有人可以理解并作出智能的选择,一旦Harry手工的解决了冲突—也许需要与Sally讨论—它可以安全的把合并的文件保存到版本库。

拷贝-修改-合并模型感觉是有一点混乱,但在实践中,通常运行的很平稳,用户可以并行的工作,不必等待别人,当工作在同一个文件上时,也很少会有交迭发生,冲突并不频繁,处理冲突的时间远比等待解锁花费的时间少。

最后,一切都要归结到一条重要的因素:用户交流。当用户交流贫乏,语法和语义的冲突就会增加,没有系统可以强制用户完美的交流,没有系统可以检测语义上的冲突,所以没有任何证据能够承诺锁定系统可以防止冲突,实践中,锁定除了约束了生产力,并没有做什么事。

Subversion实战

是时候从抽象转到具体了,在本小节,我们会展示一个Subversion真实使用的例子。

工作拷贝

你已经阅读过了关于工作拷贝的内容,现在我们要讲一讲客户端怎样建立和使用它。

一个Subversion工作拷贝是你本地机器一个普通的目录,保存着一些文件,你可以任意的编辑文件,而且如果是源代码文件,你可以像平常一样编译,你的工作拷贝是你的私有工作区,在你明确的做了特定操作之前,Subversion不会把你的修改与其他人的合并,也不会把你的修改展示给别人。

当你在工作拷贝作了一些修改并且确认它们工作正常之后,Subversion提供了一个命令可以“发布”你的修改给项目中的其他人(通过写到版本库),如果别人发布了各自的修改,Subversion提供了手段可以把这些修改与你的工作目录进行合并(通过读取版本库)。

一个工作拷贝也包括一些由Subversion创建并维护的额外文件,用来协助执行这些命令。通常情况下,你的工作拷贝每一个文件夹有一个以.svn为名的文件夹,也被叫做工作拷贝管理目录,这个目录里的文件能够帮助Subversion识别哪一个文件做过修改,哪一个文件相对于别人的工作已经过期了。

一个典型的Subversion的版本库经常包含许多项目的文件(或者说源代码),通常每一个项目都是版本库的子目录,在这种安排下,一个用户的工作拷贝往往对应版本库的的一个子目录。

举一个例子,你的版本库包含两个软件项目,paintcalc。每个项目在它们各自的顶级子目录下,见图 2.6 “版本库的文件系统”。

图 2.6. 版本库的文件系统

为了得到一个工作拷贝,你必须检出check out)版本库的一个子树,(术语“check out”听起来像是锁定或者保存资源,实际上不是,只是简单的得到一个项目的私有拷贝),举个例子,你检出 /calc,你可以得到这样的工作拷贝:

$ svn checkout http://svn.example.com/repos/calcA  calcA  calc/MakefileA  calc/integer.cA  calc/button.c$ ls -A calcMakefile  integer.c  button.c  .svn/

列表中的A表示Subversion增加了一些条目到工作拷贝,你现在有了一个/calc的个人拷贝,有一个附加的目录—.svn—保存着前面提及的Subversion需要的额外信息。

版本库的URL

Subversion可以通过多种方式访问—本地磁盘访问,或各种各样不同的网络协议,但一个版本库地址永远都是一个URL,表格2.1描述了不同的URL模式对应的访问方法。

表 2.1. 版本库访问URL

模式 访问方法 file:/// 直接版本库访问(本地磁盘)。 http:// 通过配置Subversion的Apache服务器的WebDAV协议。 https://http://相似,但是包括SSL加密。 svn:// 通过svnserve服务自定义的协议。 svn+ssh://svn://相似,但通过SSH封装。

关于Subversion解析URL的更多信息,见“Subversion版本库URL”一节。

假定你修改了button.c,因为.svn目录记录着文件的修改日期和原始内容,Subversion可以告诉你已经修改了文件,然而,在你明确告诉它之前,Subversion不会将你的改变公开。将改变公开的操作被叫做提交(committing,或者是checking in)修改到版本库。

发布你的修改给别人,你可以使用Subversion的提交(commit)命令:

$ svn commit button.cSending        button.cTransmitting file data .Committed revision 57.

这时你对button.c的修改已经提交到了版本库,如果其他人取出了/calc的一个工作拷贝,他们会看到这个文件最新的版本。

假设你有个合作者,Sally,她和你同时取出了/calc的一个工作拷贝,你提交了你对button.c的修改,Sally的工作拷贝并没有改变,Subversion只在用户要求的时候才改变工作拷贝。

要使项目最新,Sally可以要求Subversion更新她的工作备份,通过使用更新(update)命令,将结合你和所有其他人在她上次更新之后的改变到她的工作拷贝。

$ pwd/home/sally/calc$ ls -A.svn/ Makefile integer.c button.c$ svn updateU button.c

svn update命令的输出表明Subversion更新了button.c的内容,注意,Sally不必指定要更新的文件,subversion利用.svn以及版本库的进一步信息决定哪些文件需要更新。

修订版本

一个svn commit操作可以作为一个原子事务操作发布任意数量文件和目录的修改,在你的工作拷贝里,你可以改变文件内容、删除、改名和拷贝文件和目录,然后作为一个整体提交。

在版本库中,每一次提交被当作一次原子事务操作:要么所有的改变发生,要么都不发生,Subversion努力保持原子性以应对程序错误、系统错误、网络问题和其他用户行为。

每当版本库接受了一个提交,文件系统进入了一个新的状态,叫做一次修订(revision),每一个修订版本被赋予一个独一无二的自然数,一个比一个大,初始修订号是0,只创建了一个空目录,没有任何内容。

图 2.7 “版本库”可以更形象的描述版本库,想象有一组修订号,从0开始,从左到右,每一个修订号有一个目录树挂在它下面,每一个树好像是一次提交后的版本库“快照”。

图 2.7. 版本库

全局修订号

不像其他版本控制系统,Subversion的修订号是针对整个目录树的,而不是单个文件。每一个修订号代表了一次提交后版本库整个目录树的特定状态,另一种理解是修订号N代表版本库已经经过了N次提交。当Subversion用户讨论“foo.c的修订号5”时,他们的实际意思是“在修订号5时的foo.c”。需要注意的是,修订号N和M并表示一个文件需要不同。因为CVS使用每一个文件一个修订号的策略,CVS用户可能希望察看附录 A, Subversion对于CVS用户来得到更多细节。

需要特别注意的是,工作拷贝并不一定对应版本库中的单个修订版本,他们可能包含多个修订版本的文件。举个例子,你从版本库检出一个工作拷贝,最近的修订号是4:

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

此刻,工作目录与版本库的修订版本4完全对应,然而,你修改了button.c并且提交之后,假设没有别的提交出现,你的提交会在版本库建立修订版本5,你的工作拷贝会是这个样子的:

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

假设此刻,Sally提交了对integer.c的修改,建立修订版本6,如果你使用svn update来更新你的工作拷贝,你会看到:

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

Sally对integer.c的改变会出现在你的工作拷贝,你对button.c的改变还在,在这个例子里,Makefile在4、5、6修订版本都是一样的,但是Subversion会把他的Makefile的修订号设为6来表明它是最新的,所以你在工作拷贝顶级目录作一次干净的更新,会使得所有内容对应版本库的同一修订版本。

工作拷贝怎样追踪版本库

对于工作拷贝的每一个文件,Subversion在管理区域.svn/记录两项关键的信息:

  • 工作文件所作为基准的修订版本(叫做文件的工作修订版本)和

  • 一个本地拷贝最后更新的时间戳。

给定这些信息,通过与版本库通讯,Subversion可以告诉我们工作文件是处与如下四种状态的那一种:

未修改且是当前的

文件在工作目录里没有修改,在工作修订版本之后没有修改提交到版本库。svn commit操作不做任何事情,svn update不做任何事情。

本地已修改且是当前的

在工作目录已经修改,从基本修订版本之后没有修改提交到版本库。本地修改没有提交,因此svn commit会成功的提交,svn update不做任何事情。

未修改且不是当前的了

这个文件在工作目录没有修改,但在版本库中已经修改了。这个文件最终将更新到最新版本,成为当时的公共修订版本。svn commit不做任何事情,svn update将会取得最新的版本到工作拷贝。

本地已修改且不是最新的

这个文件在工作目录和版本库都得到修改。一个svn commit将会失败,这个文件必须首先更新,svn update命令会合并公共和本地修改,如果Subversion不可以自动完成,将会让用户解决冲突。

这看起来需要记录很多事情,但是svn status命令可以告诉你工作拷贝中文件的状态,关于此命令更多的信息,请看“svn status”一节。

修订版本混合的限制

作为通常的原则,Subversion期望尽可能的灵活,一个灵活性的表现就是能够在工作拷贝中混合有不同的修订版本。

起初,为什么把这种灵活性看作一种特性并没有完全看清楚,这也不是一个任务。完成了提交之后,干净的提交的文件比其他文件有更加新的版本,这看起来有些混乱,但是像以前说过的,通过svn update可以使整个版本统一起来, 怎么会有人故意的混合版本呢?

假设你的项目非常复杂,有时候需要强制地使工作拷贝的一部分“回到”某一个日期,你可以在第3章学习如何操作。或许你也希望测试某一目录下子模块早期的版本,或许你想检查某一文件过去的一系列版本在最新目录树环境下的表现。

无论你在工作拷贝中如何利用混合版本,对于这种灵活性是有限制的。

首先,你不可以提交一个不是完全最新的文件或目录,如果有个新的版本存在于版本库,你的删除操作会被拒绝,这防止你不小心破坏你没有见到的东西。

第二,如果目录已经不是最新的了,你不能提交一个目录的元数据更改。你将会在第6章学习附加“属性”,一个目录的工作修订版本定义了许多条目和属性,因而对一个过期的版本提交属性会破坏一些你没有见到的属性。

摘要

我们在这一章里学习了许多Subversion的基本概念:

  • 我们介绍了中央版本库的概念、客户工作拷贝和版本修订树。

  • 我们介绍了两个协作者如何使用Subversion发布和获得对方的修改,使用“拷贝-修改-合并”模型。

  • 我们讨论了一些Subversion跟踪和管理工作拷贝信息的方式。

现在,你一定对Subversion在多数情形下的工作方式有了很好的认识,有了这些知识的武装,你一定已经准备好跳到下一章去了,一个关于Subversion命令与特性的详细教程。