svn使用指南

SVN相关概念介绍

什么是SVN

SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS、CVS,它采用了分支管理系统,它的设计目标就是取代CVS。互联网上很多版本控制服务已从CVS迁移到Subversion。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。

Subversion 是一种集中的分享信息的系统,它的核心是版本库,储存所有的数据,版本库按照文件树形式储存数据-包括文件和目录,任意数量的客户端可以连接到版本库,读写这些文件。通过写数据,别人可以看到这些信息;通过读数据,可以看到别人的修改。

工作流程

集中式管理的工作流程如下图:

https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=3c127e50a3cc7cd9ee203c8b58684a5a/d1160924ab18972b44ba6577e6cd7b899f510a8e.jpg

集中式代码管理的核心是服务器,所有开发者在开始新一天的工作之前必须从服务器获取代码,然后开发,最后解决冲突,提交。所有的版本信息都放在服务器上。如果脱离了服务器,开发者基本上可以说是无法工作的。下面举例说明:

1.从服务器下载项目组最新代码。

2.进入自己的分支,进行工作,每隔一个小时向服务器自己的分支提交一次代码(很多人都有这个习惯。因为有时候自己对代码改来改去,最后又想还原到前一个小时的版本,或者看看前一个小时自己修改了哪些代码,就需要这样做了)。

3.下班时间快到了,把自己的分支合并到服务器主分支上,一天的工作完成,并反映给服务器。

实现方案

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

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

锁定-修改-解锁方案

许多版本控系统使用 锁定-修改-解锁 模型来解决这个问题,这是一个简单的解决方案。在这种系统中,在同一时间版本库只允许一个用户修改一个文件。首先,Barry 必须在修改前 锁定 该文件。锁定文件有点像从图书馆结束; 如果 Harry 锁定了一个文件,那么 Sally 就修改该文件。如果她试图锁定该文件,版本库会拒绝这个请求。她只能读取这个文件,并等待 Harry 结束修改并释放文件锁。在 Harry 解锁文件后,他的任务就完成了,现在 Sally 可以接手工作 - 锁定并编辑文件。

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

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

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

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

复制-修改-合并方案

Subversion,CVS,和其他版本控制系统使用copy-modify-merge模型代替锁定。在这个模型中,每个用户的客户端读取存储库并创建一个个人文件的工作副本或项目。用户并行工作,修改他们的私人复制。最后,私人复制到一个新的合并在一起,最终版本。版本控制系统通常协助合并,但最终一个人负责正确地使它发生。

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

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

Subversion 怎么做?

Subversion 缺省使用复制-修改-合并模型,大多数情况下可以满足你的需求。然而,Subversion 1.2 后还是支持锁定,如果你有不可合并的文件,或者你只是想实行强制管理策略,Subversion 仍然会提供你需要的特性。

TortoiseSVN介绍

TortoiseSVN 是一个Windows下的版本控制系统Apache™ Subversion®的客户端工具。就是说 ,TortoiseSVN常年管理 文 件 和 目 录 。文 件存储于个中央版本库中。版本库就像一个常见的文件服务器,除了它保存你对文件和目录所有的改变。这特性使得你可以恢复文件的旧版本查看历史一谁在什 么时间如何进行的修改。这就是为什么很多人认为Subversion和版本控制系统是一种“时间机器”。

某些版本控制系统也是软件配置管理(SCM)系统,这种系统经过精巧的设计,专门用来管理源代码树,并且具备许多与软件开发有关的特性 - 比如,对编程语言的支持,或者提供程序构建工具。不过 Subversion 并不是这样的系统;它是一个通用系统,可以管理任何类型的文件集,包括源代码。

日常使用技巧

  1. 检出工作副本

在Windows资源管理器里选择一个存放工作副本的目录。右键点击弹出右键菜单,选择SVN Checkout命令。然后就会看到下面的对话框:

如果输入一个并不存在的目录名,那么这个名字的目录就会被创建出来。

检出深度

你可以选择要检出的深度,它允许你指定子目录递归的深度。如果你只需要大目录中的几个子条目,你可以只检出最高层目录,然后递归的更新选择的目录。

全递归:检出完整的目录树,包含所有的文件或子目录。

直接子节点,包含文件夹:检出目录,包含其中的文件或子文件夹,但是不递归展开子文件夹。

仅文件子节点:检出指定目录,包含所有文件,但是不检出任何子文件夹。

仅此项:只检出目录。不包含其中的文件或子文件夹。

检出部分文件

方法一:

检出路径写具体路径,如:svn://192.168.1.105/project/locks

方法二:

1.检出父文件夹时检出深度使用“仅此项”。现在,你获得一个空的顶级文件夹。

2. 选中新文件夹,使用 TortoiseSVN → 版本库浏览器 来显示版本库的内容。

3.选中需要检出的文件夹然后右键菜单 → 更新项目至版本

更新工作副本

你需要定期地确保将别人所做的修改整合到你本地的工作副本中。从服务器获取更改到本地副本的过程就叫做 更新。更新的对象可以是一个文件,选中的多个文件或者对整个目录结构进行递归。要进行更新,选中要更新的文件或目录,右键单击然后选中右键菜单中的SVN Update。将会弹出一个窗口,随着更新的进行显示进度。其他人所做的更改将会合并到你的文件中,并保留同一个文件中你所做的更改。版本库不会受更新影响。

如果在更新过程中发生了 冲突 (有可能是因为你和他人修改了同一个文件的同一行并且这些更改不匹配)那么对话框会用红色显示冲突。可以通过 双击 那些行来启动外部合并工具解决冲突。

查看历史版本

当要查看你的项目在过去的某个时间是什么样子时,右键单击—TortoiseSVN—Update to reversion功能有时会很有用。但一般来说,更新单个文件到一个较早的版本不是一个好主意,因为这样就使工作副本处于一种不一致的状态。如果更新的文件改变了文件名,你甚至会发现该文件从你的工作副本中消失了,因为在较早的版本中没有叫这个名字的文件。也还会发现该条目显示正常的绿色图标重载,所以很难察觉到存在过期的文件。

如果你只是想要某文件早先版本的本地副本,从该文件的日志对话框中使用 右键菜单 → 保存版本至... 更好。或者TortoiseSVN—Update to reversion—根据日志选择版本

提交修改到版本库

将你对工作副本的修改发送给版本库,称为提交修改。但在你提交之前要确保你的工作副本是最新的。你可以直接使用:鼠标右击→SVN Update,或者,你可以先使用鼠标右击→TortoiseSV→检查修改看看哪些文件在本地或是服务器上已经有了改动。

提交对话框

如果你的工作副本是最新的,并且没有冲突,你就已经为提交做好准备了, 鼠标右击→SVN Commit, 选择你要提交的文件或文件夹点击确定提交

提交对话框将显示每个被改动过的文件,包括新增的、删除的和未受控的文件。如果你不想改动被提交,只要将该文件的复选框的勾去掉就可以了。如果你要加入未受控的文件,只要勾选该文件把它加入提交列表就可以了。

从提交列表中排除项目

有时,你经常更改一些版本控制的文件但你却不打算提交它们。这有可能说明你的构建过程中存在瑕疵 - 那些文件为什么是版本控制的?应该使用模版文件吗?但可能这是无法避免的。一个经典的原因是当你每次构建的时候,集成开发环境(IDE)更改了项目文件的时间戳。项目文件是版本控制的,因为它包含全部的构建设置。但是,仅仅因为时间戳更改了的情况下,你并不需要提交它。

为了解决这样一个棘手的问题,我们准备了一个名叫 ignore-on-commit 的更改列表。任何一个被添加到这个列表的文件在提交对话框中将不会自动选中。你仍然可以提交此文件的更改,不过你需要在提交对话框中手动选中它。

提交日志信息

确保输入描述你所提交的修改内容的日志信息。这可以帮你回顾做了什么,什么时候做的。信息的内容可长可短,许多项目规定了要包含的内容、使用的语言甚至是严格的格式。

另一个向日志消息中插入路径的方法是: 从文件列表中将文件拖拽到文本框中。

清理

如果Subversion命令不能成功完成,或许是由于服务器问题,你的工作副本可以处于不一致状态。在这种情况下,你需要使用TortoiseSVN→Clean up… 清理状态信息。

在清理对话框中,还有其他有用的选项将工作副本进入一个干净的状态。

清除密码

TortoiseSVN→Setting

解决冲突

偶尔,当你从版本库更新、合并文件时,或者切换工作副本至一个不同的 URL 时你会遇到冲突。有两种冲突:

文件冲突: 当两名(或更多)开发人员修改了同一个文件中相邻或相同的行时就会发生文件冲突

树冲突: 当一名开发人员移动、重命名、删除一个文件或文件夹,而另一名开发人员也对它们进行了移动、重命名、删除或者仅仅是修改时就会发生树冲突。

文件冲突

文件冲突发生在两个或两个以上的开发者已经改变了几行一个文件相同。颠覆你的项目一无所知,它让开发人员解决冲突。

实例:

文件‘建表语句.txt’更新时出现冲突,会额外产生三个文件,如下

‘建表语句.txt’冲突的区域被标记的文本文件中是这样的:

<<<<<<< .mine

create database `ekcpsd_1.4.2`; #本地冲突区修改的内容

use `ekcpsd_1.4.2`;

||||||| .r48 #本地冲突区修改之前的内容,为空

=======

create database `ekcpsd_1.4.2`; #版本库冲突区最新内容,也就是reversion 49的内容

>>>>>>> .r49

文件名.扩展名.mine

这是你的文件,在你更新你的工作副本之前存在于你的的工作副本中——也就是说,没有冲突标志。这个文件除了你的最新修改外没有别的东西。

文件名.扩展名.r旧版本

这是在你更新你的工作副本之前的基础版本(BASE revision)文件。也就是说,它是在你做最后修改之前所检出的文件

文件名.扩展名.r新版本

这个文件是当你更新你的工作副本时,你的 Subversion 客户端从服务器接收到的。这个文件对应于版本库中的最新版本。

解决:

建表语句.txt---鼠标右击TortoiseSVN-- Edit Conflicts---合并后保存—点击已解决

然后重新提交

树冲突

当一名开发人员移动、重命名、删除一个文件或文件夹,而另一名开发人员也对它们进行了移动、重命名、删除或者仅仅是修改时就会发生树冲突。有很多种不同的情形可以导致树冲突,而且不同的情形需要不同的步骤来解决冲突。

本地删除(Tortoise删除),当更新时有更改进入

1.开发人员 A 修改 Foo.c 并将其提交至版本库中。

2.开发人员 B 同时在他的工作副本中将文件 Foo.c 改名为 Bar.c,或者仅仅是删除了 Foo.c 或它的父文件夹。

提交开发人员 B 的工作副本会导致树冲突:

ww语句.txt---鼠标右击--- Edit Conflicts

状态信息

显示重载图标的资源管理器

现在你已经从 Subversion 版本库中检出了一份工作副本,你可以在资源管理器中看一下这些文件的图标有什么变化。这也正是 TortoiseSVN 这么流行的原因之一。TortoiseSVN 加入了被称为重载图标的功能重载了原始的文件图标。根据文件的 Subversion 状态的不同,重载的图标也不同。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/InSubVersionIcon.png 一个新检出的工作副本使用绿色的对勾做重载。表示 Subversion 状态正常.

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/ModifiedIcon.png 在你开始编辑一个文件后,状态就变成了已修改,而图标重载变成了红色感叹号。通过这种方式,你可以很容易地看出哪些文件从你上次更新工作副本后被修改过,需要被提交。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/ConflictIcon.png 如果在更新的过程中出现了冲突,图标会变成黄色感叹号。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/ReadOnlyIcon.png 如果你给一个文件设置了svn:needs-lock属性,Subversion 会让此文件只读,直到你获得文件锁。具有这个重载图标的文件来表示你必须在编辑之前先得到锁。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/LockedIcon.png 如果你拥有了一个文件的锁,并且 Subversion 状态是正常,这个重载图标就提醒你如果不使用该文件的话应该释放锁,允许别人提交对该文件的修改。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/DeletedIcon.png 这个图标表示当前文件夹下的某些文件或文件夹已经被调度从版本控制中删除,或是该文件夹下某个受版本控制的文件丢失了。Tortoise删除然后ctrl+z复现

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/AddedIcon.png 加号告诉你有一个文件或目录已经被调度加入版本控制。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/IgnoredIcon.png 横条告诉你有一个文件或目录被版本控制系统所忽略。这个图标重载是可选的。

https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/images/UnversionedIcon.png 这个图标说明文件和目录未被版本控制,但是也没有被忽略。这个图标重载是可选的。

详细状态

有时你可能想得到关于一个文件/目录的更多的细节信息而不仅是一个重载的标志。 你能得到Subversion的属性对话框中浏览到的所有信息。只需选择指定文件或目录,然后在文件菜单中选择Windows 菜单 → 属性(注意: 这是资源管理器提供的标准属性菜单,而不是TortoiseSVN 子菜单的其中之一)。在TortoiseSVN 属性对话框中已经为在Subversion控制下的文件/目录增加新的属性页。在这里你能看到所有的关于选择文件/目录的相关信息。

本地与远程状态

通常知道你修改了哪些文件以及哪些文件已经由另人修改并提交了是很有用的。这就是命令 TortoiseSVN → 检查修改 的用武之地了。这个对话框显示了所有你的工作副本中进行了任何形式的修改的的文件,也包括了当前存在的未受控的文件

选中修改的文件----右键菜单---compare with base检查你所作的本地修改。选中修改的文件----右键菜单---show differences as uninfied diff检查版本库中别人作的修改。

你也可以还原单个文件的修改。如果不小心删除了某个文件,就会显示为 缺少 而且可以使用 SVN 还原 来恢复它。选中删除的文件----右键菜单—revert恢复。

查看差别

通常你想要深入文件中了解你修改了什么。要达到这个目的,你可以选中这个文件,然后在TortoiseSVN的右键菜单中选择比较。这个操作会启动一个外部的差别检查程序,由它来比较当前文件与上一次检出或更新后的原始的副本(基础版本)。

版本日志对话框

对于每次进行修改和提交,你应该有针对性地留下日志信息。这样,你就可以在以后方便地看到你都做了什么,为什么这么做。当然这么做还是你拥有了开发过程的详细日志。

调用版本日志对话框

版本日志对话框可以获取所有的日志信息,并将其显示出来。对话框的视图分成3个面板。

1.最上方的面板显示了版本的列表。这其中包含了日期和时间,以及提交的用户和日志信息开头的部分内容。

以蓝色显示的行表示某些内容被复制到该开发版本中(可能是从一个分支中复制而来)。

2.中间的面板显示了被选中的版本的完整的日志信息。

3.最下面的面板显示了被选中版本中都对哪里文件和文件夹进行了修改。

有几种途径可以调出日志对话框:

从右键菜单的TortoiseSVN子菜单中调用

从属性页中调用

在更新结束后,从进度对话框中调用。在这里,日志对话框只显示你上一次更新以来的版本变化。

From the repository browser

获得更多信息

获得更多信息

前面板的日志对话框有一个上下文菜单,允许您获取更多的信息。

与工作副本比较

将你的工作版本与选中的版本进行比较。默认的比较工具是与 TortoiseSNV 一同发布的 TortoiseMerge,如果日志对话框是针对文件夹的,那么就会出现一个被修改的文件的列表,你可以单独地查看每个文件所做的修改。

与工作基础版本比较并追溯

追溯文件的选中版本与你工作的 BASE 版本,使用可视化差异工具显示差异。

与前一版本比较

比较选中的版本和以前版本。它与比较工作副本类似。对于文件夹,这个选项首先会显示已修改的文件对话框让你选择要比较的文件。

合并版本到...

合并选中的版本到不同的工作副本。可以通过文件夹选择对话框来确定合并到哪一个工作副本中,但是此操作没有冲突对话框,也没有尝试测试合并的机会。合并到未修改的工作副本是一个好主意,这样当合并不成功时你可以还原工作副本。当你想要将某个分支上选中的版本合并至其他分支时,这个功能很有用。

检出...

检出你选择的目录的选中版本,创建一个全新副本。它弹出对话框,让你确认URL和版本,并且选择保存的位置。

导出...

导出选择的文件/目录的选中版本。它弹出对话框,让你确认URL和版本,选择导出位置。

撤消更改

撤销本地修改

右键点击弹出右键菜单,然后选择TortoiseSVN → SVN 还原命令,将会弹出一个对话框显示你已经变更并能恢复的文件。选择那些你想要恢复的然后按确定。

撤销已经提交的改变

调用版本日志对话框---选择版本右击--revert to this reversion

单个文件恢复

选中文件右击---Tortoise SVN---Update to reversion

创建branch

在trunk目录上右键依次选择"TortoiseSVN" -> "Branch/tag...",在弹出窗口的"To URL"中填入分支的地址

设置log后点击ok分支便建立了。这个操作速度非常快,新建的branch在repository中其实类似于 Unix 里的硬连接,它意思是代替一个版本库里的完整的复制,创建一个内部的链接,指向一个具体的版本树。结果分支和标记迅速被创建,并且几乎没有在版本库里占据任何额外的空间。

Check out分支

右键TestSVN目录选择"TortoiseSVN Update"即可将刚刚建立的分支下载回本地。进入/branches/1.4.0目录下你会发现其文件结构和/trunk/1.4.0一模一样。

合并

分支用来维护独立的开发支线,在一些阶段,你可能需要将分支上的修改合并到主干,或者相反。

合并指定版本范围

这个方法覆盖了你已经在分支(或者主干)上做出了一个或多个修改,并且你想将这些修改应用到不同分支的情况。

实例步骤:

  1. branch提交一个新文件
  2. trunk紧接着提交一个修改
  3. branch再次提交一个修改

为了防止在“错误”的道路上越走越远,现在branch意识到是时候和trunk来一次同步了(将trunk合并到branch)

首先,在本地trunk中先update一下,有冲突的解决冲突,保证trunk和repository已经完全同步,然后在/branch/doc1.4.0上右键,依次选择"TortoiseSVN" -> “Merge...”,在弹出的窗口中选择第一项"Merge a range of revision",这个类型的Merge适用于将某个分支或主线上提交的多个revision间的变化合并到另外一个分支上。点击next后,出现如下窗口:

由于是要从trunk合并到branch,理所当然这里的"URL to merge from"应该填trunk的路径,"Revision range to merge"很好理解,就是你要将trunk的哪些revision所对应的变化合并到branch中,可以是某一连串的revision,比如4-7,15-HEAD,也可以是某个单独的revision号。由于在r136中,trunk提交了一个修改,所以这里的revision只需填136即可。点击next后出现下图:

在这里只需保留默认设置即可。在点击Merge按钮前你可以先Test merge一把,看成功与否,以及merge的详细信息。点击Merge按钮后trunk所做的修改将同步到branch中。

提交合并后的branch,至此,branch已经完全和trunk同步,branch和trunk的代码相处很融洽,没有任何冲突,如果branch已经开发结束,那是时候将branch合并回trunk了。

合并两个不同的目录树

如果您正使用此方法将一个特性分支合并回主干,你需要从一个主干工作副本内启动合并向导。

在 起始: 区域输入 主干 的完整文件夹地址。这听起来像是错了,但请记住主干是要添加分支更改的起始点。你也可以点击 ... 浏览版本库。

在到:域输入关注的分支中文件夹的全路径。

在开始版本和结束版本 域,输入两个树被同步的最后一个版本号。如果你确信没有其他人提交,两个都可是输入 HEAD。如果在同步时可能有人提交的话,使用清楚的版本号以便面丢失最新提交。点击下一步如下

也可以点击“Test merge”测试合并看成功与否,以及merge的详细信息。

点击merge合并并提交合并后的trunk

合并两个目录树后两个树的内容一致:当从主干上的变化合并到分支上时,意味着分支已经可以作为主干,因此合并目录树相当于从分支创建一个分支到主干,只不过主干多了之前的日志

linux下常用命令

检出

svn checkout svn://192.168.1.105:/project --username=liwenbin

更新

svn update project/

可以使用-r参数指定版本

svn update -r 20 project/

往版本库添加新的文件

svn add PATH

打印工作副本文件和目录的状态。

svn status

删除

svn delete PATH

提交到版本库

svn commit -m '注释内容' PATH

服务器技术交流群请加微信 YJZyjz