关于SVN的学习,大概是两年多以前为了合作开发学的,确切的说当时的学很是简单,开始时简单合作,所以学的也够用,但是随着后来的项目参与的人越来越多,更多的SVN使用问题不断出现,深感有较为系统学习一下的必要,恰好最近的项目接近尾声,又恰好遇见几本关于SVN的书,故把自己的总结和所学分享一下。
保存什么
SVN中要存放什么?这个是我们需要关心的一个问题,不用放的存进去,不但浪费空间也会拖慢Export的速度。源代码是必然要保存的,但是根据代码生成的函数API文档需不需要,软件开发文档需不需要?简单的说,我们可以这么问:如果没有此文件的最新版本,软件能不能开发、构建、测试、发布?如果软件开发能正常进行,那就不必放进去,比如根据代码生成的函数API文档,每次都可以根据代码重新生成,存入SVN,浪费磁盘空间事小,与代码不同步才事大。
存储原理
SVN存储采用的是增量算法存储二进制文件,也就是说对源代码而言,每次都保存提交的完整版本显然有些浪费,所以每次提交,SVN存储的只是不同版本文件之间的差异部分,同时SVN保存最新版本的完整版,“最智能”的是,SVN自己会根据一定的情况保存个别版本的完整版,这样根据x=n-1,就可以获取任意版本x的完整版内容。
SVN使用的是典型的文件和目录结构。
版本原理
目录和文件是SVN管理的核心内容,文件、目录的改变、移动都会被SVN记录。SVN的提交具有原子性,也就是说除非本次要提交的文件全部提交成功,否则一个文件也不会提交到SVN库中,在这个原子操作中,非常重要的一个步骤是,把本次提交的改动打包,并给本次改动写一个编号,所以对每个文件而言,编号并不是连续的,如下图:
也就是说版本号意味着经历了对仓库进行了多少次修改,初始版本为0,代表建库之初的空结构;也可以形象的认为版本号是整个库在每次修改后的一个快照。
.svn
说完版本号,再来说说.svn文件夹。
SVN在1.6之前,工作副本中的每个文件夹下都有一个.svn子文件夹;1.6之后,只在工作副本下有一个.svn文件夹。这个文件夹是SVN创建和维护的,用来协助各种SVN命令的执行,它可以帮助SVN识别哪些文件做过修改,哪些文件相对于库中的已过期,可以把.svn文件夹看做本地缓存。.svn是如何做到的?
之所以.svn文件夹有此作用,与它记录的信息有关:
- 本地副本最后一次有效更新的版本号、时间戳。
- 仓库中文件在本地的基准缓存(我认为是上面提到的SVN的智能快照)
操作原理
update和commit
- 本地副本版本号同于仓库版本号且无内容更改,说明本地文件没有发生任何变化,执行update或commit不进行任何操作。
- 本地副本版本号同于仓库版本号且有内容更改,说明本地文件更新,执行update无操作,可以正常commit。
- 本地副本版本号低于仓库版本号且无内容修改,说明库中有其它文件更新,当前文件未变,执行commit无操作,可以正常执行update。
- 本地副本版本号低于仓库版本号且有内容修改,说明这个文件或目录已经被更改,需要先进行update才能commit,防止冲突。
diff
- 检查本地修改
- 比较工作副本与仓库的区别
- 比较版本库的区别
代码回滚
svn merge -r 28:25 pom.xml
意思是将pom.xml还原到25版本。
解决冲突
为什么会有冲突?
- 两个人修改了不同的文件,不会冲突。
- 两个人修改了同一个文件的不同位置,不会冲突,SVN会很聪明的合并两者的不同。
- 两个人修改了同一个文件的相同位置,才会发生冲突。
乐观锁
这个锁真的很乐观,实际上,根本没有锁,当两个人修改相同的一行的代码时,提示如下
<<<<<<< .mine
<!--test note2.01-->
=======
<!--test note2.0-->
>>>>>>> .r3842
然后,这两个人交流,找到解决方法,最终删除这些符号,然后提交。
悲观锁
如果两个人修改了相同的代码文件的不同位置,svn可以合并,但是如果是.xls这样的文件,两个人的修改是不可以合并的,这时,为了防止冲突就需要加锁,SVN提供了Get lock和Release lock操作,一旦加锁后,其他人不能修改或提交关于此文件的改动。
需要注意,这个lock不仅和用户有关,和工作副本也有关:你用用户ld在D盘下的工作副本加锁了,同一台机器上C盘下的工作副本,用户ld写也不能修改被加锁的文件;一旦加锁的文件commit后,SVN就会认为这个文件已经处理好了,会自动解锁。
如果是代码文件,非常推荐使用乐观锁的形式;即使不得不使用锁,锁住的时间也要尽可能的短。
有冲突时,同时需要解决的是交流和管理的问题:为什么多个人会修改同一行代码,是分工有问题或是交流有问题。
使用流程
SVN较为合理的使用流程(以代码为例):
结尾
下面的截图是官方文档中未完全汉化的一段内容,解释的是为什么当你commit后,使用svn log命令不会显示你刚才提交的改动:
只是跟你说一下,以后可以多读读官方文档了。
推荐
《svnbook-1.6-zh-r3600》(官方说明书,未完全汉化)