最近在公司又开始玩SVN啦,这里给大家总结一下,基本上在公司不是用git就是用SVN进行代码管理,作为程序员,这些工具的使用还是需要熟悉了解一下的,本期孙叫兽给大家分享一下SVN相关的知识点,做到会用即可。不懂得可以查查相关文档。
SVN 官网:https://subversion.apache.org/
Github SVN 源码:https://github.com/apache/subversion
简介
Subversion(SVN) 是一个开源的版本控制系统, 也就是说 Subversion 管理着随时间改变的数据。这些数据放置在一个中央资料档案库(repository) 中。这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动。这样你就可以把档案恢复到旧的版本, 或是浏览文件的变动历史。
主要功能
- (1)目录版本控制 CVS 只能跟踪单个文件的历史, 不过 Subversion 实作了一个 "虚拟" 的版本控管文件系统, 能够依时间跟踪整个目录的变动。目录和文件都能进行版本控制。
- (2)真实的版本历史 自从CVS限制了文件的版本记录,CVS并不支持那些可能发生在文件上,但会影响所在目录内容的操作,如同复制和重命名。除此之外,在CVS里你不能用拥有同样名字但是没有继承老版本历史或者根本没有关系的文件替换一个已经纳入系统的文件。在Subversion中,你可以增加(add)、删除(delete)、复制(copy)和重命名(rename),无论是文件还是目录。所有的新加的文件都从一个新的、干净的版本开始。
- (3)自动提交 一个提交动作,不是全部更新到了档案库中,就是不完全更新。这允许开发人员以逻辑区间建立并提交变动,以防止当部分提交成功时出现的问题。
- (4)纳入版本控管的元数据 每一个文件与目录都附有一組属性关键字并和属性值相关联。你可以创建, 并儲存任何你想要的Key/Value对。属性是随着时间来作版本控管的,就像文件容一样。
- (5)选择不同的网络层 Subversion 有抽象的档案库存取概念, 可以让人很容易地实现新的网络机制。Subversion 可以作为一个扩展模块嵌入到Apache HTTP 服务器中。这个为Subversion提供了非常先进的稳定性和协同工作能力,除此之外还提供了许多重要功能: 举例来说, 有身份认证, 授权, 在线压缩, 以及文件库浏览等等。还有一个轻量级的独立Subversion服务器, 使用的是自定义的通信协议, 可以很容易地通过 ssh 以 tunnel 方式使用。
- (6)一致的数据处理方式 Subversion 使用二进制差异算法来表示文件的差异, 它对文字(人类可理解的)与二进制文件(人类无法理解的) 两类的文件都一视同仁。这两类的文件都同样地以压缩形式储存在档案库中, 而且文件差异是以两个方向在网络上传输的。
- (7)有效的分支(branch)与标签(tag) 在分支与标签上的消耗并不必一定要与项目大小成正比。Subversion 建立分支与标签的方法, 就只是复制该项目, 使用的方法就类似于硬连接(hard-link)。所以这些操作只会花费很小, 而且是固定的时间。
- (8)Hackability Subversion没有任何的历史包袱; 它主要是一群共用的 C 程序库, 具有定义完善的API。这使得 Subversion 便于维护, 并且可被其它应用程序与程序语言使用。
基本概念
- repository(源代码库):源代码统一存放的地方
- Checkout(提取):当你手上没有源代码的时候,你需要从repository checkout一份
- Commit(提交):当你已经修改了代码,你就需要Commit到repository
- Update (更新):当你已经Checkout了一份源代码, Update一下你就可以和Repository上的源代码同步,你手上的代码就会有最新的变更
日常开发过程其实就是这样的(假设你已经Checkout并且已经工作了几天):Update(获得最新的代码) -->作出自己的修改并调试成功 --> Commit(大家就可以看到你的修改了) 。
如果两个程序员同时修改了同一个文件呢, SVN 可以合并这两个程序员的改动,实际上SVN管理源代码是以行为单位的,就是说两个程序员只要不是修改了同一行程序,SVN都会自动合并两种修改。如果是同一行,SVN 会提示文件 Conflict, 冲突,需要手动确认。
SVN 安装
下载地址:
https://sourceforge.net/projects/win32svn/
无脑安装即可,安装成功后在桌面右击会有SVN相关checkout选项。
生命周期
创建版本库
版本库相当于一个集中的空间,用于存放开发者所有的工作成果。版本库不仅能存放文件,还包括了每次修改的历史,即每个文件的变动历史。
Create 操作是用来创建一个新的版本库。大多数情况下这个操作只会执行一次。当你创建一个新的版本库的时候,你的版本控制系统会让你提供一些信息来标识版本库,例如创建的位置和版本库的名字。
检出
Checkout 操作是用来从版本库创建一个工作副本。工作副本是开发者私人的工作空间,可以进行内容的修改,然后提交到版本库中。
更新
顾名思义,update 操作是用来更新版本库的。这个操作将工作副本与版本库进行同步。由于版本库是由整个团队共用的,当其他人提交了他们的改动之后,你的工作副本就会过期。
让我们假设 Tom 和 Jerry 是一个项目的两个开发者。他们同时从版本库中检出了最新的版本并开始工作。此时,工作副本是与版本库完全同步的。然后,Jerry 很高效的完成了他的工作并提交了更改到版本库中。
此时 Tom 的工作副本就过期了。更新操作将会从版本库中拉取 Jerry 的最新改动并将 Tom 的工作副本进行更新。
执行变更
当检出之后,你就可以做很多操作来执行变更。编辑是最常用的操作。你可以编辑已存在的文件,例如进行文件的添加/删除操作。
你可以添加文件/目录。但是这些添加的文件目录不会立刻成为版本库的一部分,而是被添加进待变更列表中,直到执行了 commit 操作后才会成为版本库的一部分。
同样地你可以删除文件/目录。删除操作立刻将文件从工作副本中删除掉,但该文件的实际删除只是被添加到了待变更列表中,直到执行了 commit 操作后才会真正删除。
Rename 操作可以更改文件/目录的名字。"移动"操作用来将文件/目录从一处移动到版本库中的另一处。
复查变化
当你检出工作副本或者更新工作副本后,你的工作副本就跟版本库完全同步了。但是当你对工作副本进行一些修改之后,你的工作副本会比版本库要新。在 commit 操作之前复查下你的修改是一个很好的习惯。
Status 操作列出了工作副本中所进行的变动。正如我们之前提到的,你对工作副本的任何改动都会成为待变更列表的一部分。Status 操作就是用来查看这个待变更列表。
Status 操作只是提供了一个变动列表,但并不提供变动的详细信息。你可以用 diff 操作来查看这些变动的详细信息。
修复错误
我们来假设你对工作副本做了许多修改,但是现在你不想要这些修改了,这时候 revert 操作将会帮助你。
Revert 操作重置了对工作副本的修改。它可以重置一个或多个文件/目录。当然它也可以重置整个工作副本。在这种情况下,revert 操作将会销毁待变更列表并将工作副本恢复到原始状态。
解决冲突
合并的时候可能会发生冲突。Merge 操作会自动处理可以安全合并的东西。其它的会被当做冲突。例如,"hello.c" 文件在一个分支上被修改,在另一个分支上被删除了。这种情况就需要人为处理。Resolve 操作就是用来帮助用户找出冲突并告诉版本库如何处理这些冲突。
提交更改
Commit 操作是用来将更改从工作副本到版本库。这个操作会修改版本库的内容,其它开发者可以通过更新他们的工作副本来查看这些修改。
在提交之前,你必须将文件/目录添加到待变更列表中。列表中记录了将会被提交的改动。当提交的时候,我们通常会提供一个注释来说明为什么会进行这些改动。这个注释也会成为版本库历史记录的一部分。Commit 是一个原子操作,也就是说要么完全提交成功,要么失败回滚。用户不会看到成功提交一半的情况。
SVN 创建版本库
进入 /opt/svn/sunjiaoshou01/conf 目录,修改默认配置文件配置,包括 svnserve.conf、passwd、authz 配置相关用户和权限。
1、svn 服务配置文件 svnserve.conf
svn 服务配置文件为版本库目录中的文件 conf/svnserve.conf。该文件仅由一个 [general] 配置段组成。
代码语言:javascript复制[general]
anon-access = none
auth-access = write
password-db =/home/svn/passwd
authz-db =/home/svn/authz
realm = tiku
- anon-access: 控制非鉴权用户访问版本库的权限,取值范围为 "write"、"read" 和 "none"。即 "write" 为可读可写,"read" 为只读,"none" 表示无访问权限,默认值:read。
- auth-access: 控制鉴权用户访问版本库的权限。取值范围为 "write"、"read" 和 "none"。即"write"为可读可写,"read"为只读,"none"表示无访问权限,默认值:write。
- authz-db: 指定权限配置文件名,通过该文件可以实现以路径为基础的访问控制。除非指定绝对路径,否则文件位置为相对conf目录的相对路径,默认值:authz。
- realm: 指定版本库的认证域,即在登录时提示的认证域名称。若两个版本库的认证域相同,建议使用相同的用户名口令数据文件。默认值:一个UUID(Universal Unique IDentifier,全局唯一标示)。
2、用户名口令文件 passwd
用户名口令文件由 svnserve.conf 的配置项 password-db 指定,默认为 conf 目录中的 passwd。该文件仅由一个 [users] 配置段组成。
[users] 配置段的配置行格式如下:
代码语言:javascript复制[users]
admin = admin
thinker =123456
3、权限配置文件
权限配置文件由 svnserve.conf 的配置项 authz-db 指定,默认为 conf 目录中的 authz。该配置文件由一个 [groups] 配置段和若干个版本库路径权限段组成。
[groups]配置段中配置行格式如下:
代码语言:javascript复制[groups]
g_admin = admin,thinker
[admintools:/]@g_admin= rw
*=[test:/home/thinker]
thinker = rw
*= r
SVN 检出操作
我们创建了版本库sunjiaoshou01,URL为svn://192.168.0.1/sunjiashou01,svn用户user01有读写权限。
我们就可以通过这个URL在客户端对版本库进行检出操作。
svn checkout http://svn.server.com/svn/project_repo --username=user01 以上命令将产生如下结果:
代码语言:javascript复制root@sunjiaoshou:~/svn# svn checkout svn://192.168.0.1/sunjiaoshou01--username=user01
A sunjiaoshou01/trunk
A sunjiaoshou01/branches
A sunjiaohsou01/tags
Checkedout revision 1.
检出成功后在当前目录下生成sunjiaoshou01副本目录。查看检出的内容
代码语言:javascript复制root@sunjiaoshou:~/svn# ll sunjiaoshou01/
total 24
drwxr-xr-x 6 root root 4096Jul2119:19./
drwxr-xr-x 3 root root 4096Jul2119:10../
drwxr-xr-x 2 root root 4096Jul2119:19 branches/
drwxr-xr-x 4 root root 4096Jul2119:19.svn/
drwxr-xr-x 2 root root 4096Jul2119:19 tags/
drwxr-xr-x 2 root root 4096Jul2119:19 trunk/
SVN 解决冲突
版本冲突原因:
假设 A、B 两个用户都在版本号为 100 的时候,更新了 kingtuns.txt 这个文件,A 用户在修改完成之后提交 kingtuns.txt 到服务器, 这个时候提交成功,这个时候 kingtuns.txt 文件的版本号已经变成 101 了。同时B用户在版本号为 100 的 kingtuns.txt 文件上作修改, 修改完成之后提交到服务器时,由于不是在当前最新的 101 版本上作的修改,所以导致提交失败。
SVN 提交操作
我们检出了版本库sunjiaoshou01,对应的目录放在
/home/user01/sunjiaoshou01中,下面我们针对这个库进行版本控制。
查看工作副本中的状态
代码语言:javascript复制root@sunjiaoshou:~/svn/sunjiaoshou01/trunk# svn status
A readme
此时 readme的状态为A,它意味着这个文件已经被成功地添加到了版本控制中。为了把 readme 存储到版本库中,使用 commit -m 加上注释信息来提交。如果你忽略了 -m 选项, SVN会打开一个可以输入多行的文本编辑器来让你输入提交信息。
代码语言:javascript复制root@sunjiaoshou:~/svn/sunjiaoshou01/trunk# svn commit -m "SVN readme."Adding readme
Transmitting file data .Committed revision 8.
svn commit -m "SVN readme."
SVN 版本回退
当我们想放弃对文件的修改,可以使用 SVN revert 命令。
代码语言:javascript复制root@sunjiaoshou:~/svn/sunjiaoshou01/trunk# svn revert readme Reverted'readme'
进行 revert 操作之后,readme 文件恢复了原始的状态。revert 操作不单单可以使单个文件恢复原状, 而且可以使整个目录恢复原状。
假如我们想恢复一个已经提交的版本怎么办。
为了消除一个旧版本,我们必须撤销旧版本里的所有更改然后提交一个新版本。这种操作叫做 reverse merge。
首先,找到仓库的当前版本,现在是版本 22,我们要撤销回之前的版本,比如版本 21。
代码语言:javascript复制svn merge -r 22:21 readme
SVN 查看历史信息
通过svn命令可以根据时间或修订号去除过去的版本,或者某一版本所做的具体的修改。以下四个命令可以用来查看svn 的历史:
- svn log: 用来展示svn 的版本作者、日期、路径等等。
- svn diff: 用来显示特定修改的行级详细信息。
- svn cat: 取得在特定版本的某文件显示在当前屏幕。
- svn list: 显示一个目录或某一版本存在的文件。
SVN分支
Branch 选项会给开发者创建出另外一条线路。当有人希望开发进程分开成两条不同的线路时,这个选项会非常有用。
比如项目 demo 下有两个小组,svn 下有一个 trunk 版。
由于客户需求突然变化,导致项目需要做较大改动,此时项目组决定由小组 1 继续完成原来正进行到一半的工作(某个模块),小组 2 进行新需求的开发。
那么此时,我们就可以为小组2建立一个分支,分支其实就是 trunk 版(主干线)的一个copy版,不过分支也是具有版本控制功能的,而且是和主干线相互独立的,当然,到最后我们可以通过(合并)功能,将分支合并到 trunk 上来,从而最后合并为一个项目。
SVN 标签(tag)
版本管理系统支持 tag 选项,通过使用 tag 的概念,我们可以给某一个具体版本的代码一个更加有意义的名字。
Tags 即标签主要用于项目开发中的里程碑,比如开发到一定阶段可以单独一个版本作为发布等,它往往代表一个可以固定的完整的版本,这跟 VSS 中的 Tag 大致相同。
这种基本操作比较简单,和git这种思维基本一致的代码指令操作,如果熟练使用git的话,这个过一遍知识点即可,使用SVN一般不用命令就用可视化工具好点!
好啦,本期SVN内容孙叫兽就分享到这里,我们下期见!