版本管理工具TortoiseSVN使用教程
(整理自网友的博客以及一些文档)
svn(subversion)是近年来崛起的版本管理工具,是cvs的接班人。目前,绝大多数开源软件都使用svn作为代码版本管理软件。有一个简单但不十分纾确比喻: SVN = 版本控制 + 备份服务器简单的说,您可以把SVN当成您的备份服务器,更好的是,他可以帮您记住每次上传到这个服务器的档案内容。并且自动的赋予每次的变更一个版本。
通常,我们称用来存放上传档案的地方称做Repository。用中文来说,有点像是档案仓库的意思。不过,通常我们还是使用Repository这个名词。基本上,第一次我们需要有一个新增(add)档案的动作,凡想要备份的档案放到Repository上面。日后,当您有任何修改时,都可以上传到Repository上面,上传已经存在且修改过的档案叫做commit,也就是提交修改给SVN server的意思。针对每次的commit,SVN server都会赋予他一个新的版本。同时,也会把每次上传的时间记录下来。日后,因为某些因素,如果您需要从Repository下载曾经提交的档案。您可以直接选择取得最新的版本,也可以取得任何一个之前的版本。如果忘记了版本,还是可以靠记忆帝试取得某个日期的版本。
一、基础知识
1. SVN能帮助我们干嘛?
备份工作档案是十分重要的。您游远不知道计算机上的硬盘何时会坏掉。根据经验滕则再加上摩菲定理,坏事情往往都发生在最重要的时刻。例如,要release东西的前一刻,硬盘完全坏掉,无滕修复。所以,常常备份工作数据是非常重要的。大部分公司的server都会有专门的备份机制,甚至是异地备援。绝对比放在自己的计算机里头,或是随身碟上面来的安全。
版本控管非常重要。您无滕保证手头上最新版本游远都是对的。很多时候,在经过数天努力工作后,您才发现走错方向。需要帆所有的修改回复到数天前版本。溡有几个人能够完全记住自己修改过什么东西。如果溡有做好版本控管,那么,最差的状况帱是要全部重来。
伙伴间的数据同步也是非常重要的。很多时候,除了您个人外,还有其它的伙伴也需要您的档案。怎么把最新的档案提供给伙伴呢?用e-mail?根据经验,用e-mail是一个很差的办滕。到了最后,根本帱不知道哪一币e-mail才是新的。如果溡有一个好的办滕,备份不同版本是很耗费硬盘空间的。例如:您有一个总共10MB的目录,使用单纯的档案备份。如果有10个版本帱会变成100MB。20个版本帱有200MB。如果,不想备份这么多版本,势必帱是要减帑备份的次数。拉长备份周期帆会导致数据遗失的危险性增高。把旧的不需要的备份删除?根据经验,只要时间一拉长,您跟本帱不知道一个月以前的版本是重要或者是不重要。
2. SVN版本控制模型Copy-Modify-Merge(拷贝-修改-合并)
当你用subversion进行版本控制时,Subversion会记录你对Repository进行的每一次修改(包括添加,修改,删除等等),每修改一次Repository都会产生一个新的Revision(修订版本号),不同的Revision代表了不同时刻Repository的状态,因此我们可以用这个Revision回朔任意时刻Repository的状态,就像时间机器一样,也就是说某一Revision就是Repository在某一时刻的一个“快照”。
注意:Revision不是针对某一个文件或者目录,而是针对整个Repository而言的。每修改一次Repository,Revision都会增加1。
Subversion的版本控制模型是一种叫做Copy-Modify-Merge(拷贝-修改-合并)的模型。
考虑这种情况:
张三和李四是公司同一个部门的同事,他们共同维护一个文本文件a.txt,并且对该文件进行版本控制,因此他们把这个文件放到一个Repository上共同维护该文件。周一上午9点,张三和李四同时想对a.txt文件进行修改,于是他们同时从Repository上取得该文件的最新版本(Revision 10),然后进行修改。过了三分钟,张三首先完成了修改,他在该文件的第五行修改了一个单词的拼写(将Typo改为Type),于是张三对修改后的文件执行Commit命令,将修改提交到服务器端的Repository中。这时Repository的Revision变为11。六分钟过后,李四也完成了他的修改,他修改了该文件第十行上的一个单词拼写(将He改为She),于是他也对修改后的文件执行Commit命令,这时Subversion在提交修改时会发现,李四修改的文件是Revision10的a.txt文件,而不是最新的Revision 11的a.txt文件。于是,Subversion提示李四在提交修改前,应该先将Working Copy更新到最新版本,李四执行Update命令将Working Copy更新到Revision 11,这时Subversion会提示已经完成合并,李四的a.txt文件的第五行的“Typo”已经变为了“Type”,第十行还是“She”,就是说Subversion已经将张三的修改“合并”到李四的a.txt文件中了。之后,李四再执行Commit命令,就能将他对第十行的修改(将He改为She)提交到服务器端的Repository中了(生成Revision 12)。
但是这种合并在某些情况下会变得复杂一些,
比如:李四对a.txt文件的修改并不是第十行,而是与张三同样修改第五行的单词,李四将“Typo”改为“Typr”,并且提交修改,这时Subversion会提示李四在提交修改前,应该先将Working Copy更新到最新版本,李四执行Update命令将Working Copy更新到Revision 11,这时Subversion将Revision11的a.txt文件与李四修改的a.txt文件进行合并时发现李四修改的同样是第五行,于是 Subversion就无法判断是李四的修改(“Tpyr”)正确还是张三的修改(“Type”)正确,因为他们都是在Revision10的a.txt基础上作的修改。这种情况叫做Conflict(冲突),a.txt文件的图标会变成一个黄色三角。这时,只能依靠李四自己去判断到底第三行应该修改为“Typr”还是“Type”。当李四确定修改之后,在a.txt文件上单击右键,TortoiseSVN->Resolved告诉Subversion已经解决了Conflict。这时再执行Commit命令就能提交修改 (生成Revision 12)。Subversion这种控制方式保证了你对文件所作的修改都是基于文件的最新版本。
3. SVN版本控制模型Lock-Modify-Unlock(锁定-修改-解锁)
Copy-Modify-Merge(拷贝-修改-合并)的模型在对文本文件进行版本控制时工作的很好,但是有些需要进行版本控制的文件并不是文本文件,比如说图像文件,这种模型在这种情况下就不能正常工作了,因为文本文件可以合并,而二进制文件则无法合并。所以Subversion从1.2开始支持一种叫Lock-Modify-Unlock(锁定-修改-解锁)的版本控制模型。在 Windows下最常用的版本控制软件Visual Source Safe(VSS)就是采用这种模型。这种模型要求在对一个文件修改前首先要锁定这个文件,然后才能修改,这时,别人将无法对该文件进行修改,当修改完后再释放锁,使其他人可以对该文件进行锁定,然后修改。锁定文件的方法是:TortoiseSVN->Get Lock...再点OK按钮,这时就完成了对文件的锁定。这时,如果其他人想对文件进行锁定时,Subversion会对他提示该文件已经被别人锁定。当你修改完文件后,然后单击右键,SVN Commit...,将修改提交,默认情况下,提交的时候就会对该文件解锁,如果你想仍然锁定该文件,请在commit时弹出的对话框中选中keep lock复选框。
Subversion预定义一个叫“svn:needs-lock”的附加属性(关于附加属性,可看做特殊文件内容),它与上面提到的文件锁定有关。
考虑这种情况,张三和李四同时想对一个图片文件a.jpg作修改,张三在修改时先将该文件锁定,然后进行修改,同时李四也开始对该文件进行修改,但李四忘记了对非文本文件进行修改时应该先锁定该文件。张三首先对该文件修改完毕,于是张三向服务器提交了他的修改。之后,李四也完成了修改,当他提交修改时,Subversion提示李四的文件版本不是最新的,在Commit之前应先更新 a.jpg到最新版本,由于图片文件无法合并,这就意味着张三和李四之间必定有一个人的修改会作废。
应用“svn:needs-lock”属性可以避免这个问题。当一个文件拥有“svn:needs-lock”属性时,该文件在没有锁定时,文件的图标是灰色的,表示该文件是一个只读文件(该文件的 Windows只读属性的复选框为选中),这个灰色的图标就会提醒想对该文件进行修改的人,在修改该文件之前应该首先锁定该文件。锁定该文件之后,文件的只读属性就会去掉了,一旦释放掉锁,文件的图标又会变成灰色,文件也会变成只读的了。李四在这种情况下就会避免在没有锁定文件时对文件进行修改。对非文本文件添加“svn:needs-lock”属性应该在将该文件第一次添加到Repository时就设置,当然,一个文件可以在任意时刻添加附加属性,这样做是为了减少李四所遇到的那个问题发生的几率。
具体的方法是:
首先将a.jpg文件拷贝到Working Copy中,然后在该文件上单击右键,TortoiseSVN->Add,告诉Subversion要将该文件纳入版本控制,接着在该文件上单击右键并选中属性,在弹出的属性对话框中选中Subversion页。在下拉框中选中“svn:needs-lock”,并在下面的文本框中填入“*”(其实这里填什么都无所谓,只要文件有“svn:needs-lock”附加属性就行),之后点Set按钮“svn:needs-lock”附加属性就设置好了。然后执行Commit命令提交修改。这时当其他人执行Update时,a.jpg就会添加到他们的Working Copy中,并且文件的附加属性也会随文件一起被得到。可以看到a.jpg此时的图标就是灰色的,文件的Windows属性也是只读的。
4. 混合版本
Subversion 的Working Copy被设计成一种能够包含不同版本的文件共存的形式。比如F:\Project1是一个Working Copy,该目录下有两个文件a.txt和b.txt。执行Update命令,将Working Copy更新到最新版本(Revision 24)。这时,a.txt和b.txt的Revision都是24(其实对于单个文件来说并不存在Revision,Revision是对于整个 Repository而言的,这里所指的是Repository的Revision24所存储的a.txt和b.txt,但为了方便而采用这种描述方式,请注意,下同)。之后,你的同事修改了a.txt,并且提交了修改,这时Repository的Revision就变成25了。注意,这时你没有再次执行 Update,因此你的Working Copy的Revision还是24。这时你修改了b.txt文件,并提交修改。因为Revision25并没有对b.txt文件进行修改,因此你对 b.txt文件的修改是基于b.txt文件最新的版本,所以不会出现Conflict。当你提交b.txt的修改后,产生Revision26。这时你会发现你的Working Copy中的a.txt文件并不是Revision25中的a.txt文件,它还是Revision24的a.txt文件,而你的b.txt文件是 Revision26的b.txt文件。也就是说当你Commit时,你的Working Copy中只有你提交的那些文件是最新版本,而其他没有修改的文件并不会更新为最新版本。这样就造成了你的Working Copy由不同的Revision文件所组成(Revision24的a.txt文件和Revision26的b.txt文件)。
前面说过在提交修改前必须保证你是在文件的最新版本基础上修改,如果在这种混合版本的情况下,怎样才能知道当前Working Copy中的文件是否为最新版本?在前面所说的“.svn”目录中有一个文件名为“entries”的文件,该文件记录了当前Working Copy中的每一个文件的Revision,因此当你Commit时,Subversion会从该文件中取得你提交文件的Revision,再与 Repository的最新Revision一比较就可以知道你修改的文件是否基于该文件的最新版本。
5“.svn”目录
在客户端Working Copy的每一层目录中都会有一个“.svn”目录,该目录是Subversion进行管理用的目录。不要手动修改其中的文件。该目录存储了Working Copy的一个副本(实际存储副本的地方是F:\project1\.svn\text-base目录),比如:F:\Project1是一个Working Copy,该目录下有两个文件a.txt和b.txt还有一个子目录ccc,子目录ccc中还有一个d.txt文件。“.svn”目录中存储的是你最近一次执行完Update或者Commit命令之后当前目录中文件的副本,比如:F:\project1\.svn\text-base中存储的a.txt和 b.txt是最近一次执行完Update或者Commit命令之后F:\project1下的a.txt和b.txt的拷贝。也就是说你所作的修改都是基于“.svn”目录存储的那些文件。这种机制可以让我们在不连接网络的情况下,将Working Copy中的文件恢复到修改之前的状态。Subversion 的Revert命令就是利用了这种机制来实现的。比如你修改了F:\project1\a.txt文件,这时你又改变了主意想放弃对该文件的修改,你可以单击右键,TortoiseSVN->Revert,修改过的F:\project1\a.txt文件就会被F:\project1\.svn \text-base中a.txt文件的副本所替代,使得a.txt恢复到修改前的状态。Working Copy中每一个子目录下都会有一个“.svn”目录,并不是只有最上层目录才有“.svn”目录。所以,F:\project1\ccc下也有一个“.svn”目录,该目录存储的是F:\project1\ccc\d.txt的副本(d.txt的副本位于F:\project1\ccc\.svn \text-base)。也就是说每个“.svn”目录只存储同级目录中的“文件”副本,而不存储“目录”副本。“.svn”目录存有许多重要的内容,所以前面说在删除文件或目录时,必须用TortoiseSVN->Delete,而不能用“Delete”键来删除文件或目录,尤其是对于目录的删除。
二、常用命令与操作
1. 安装及下载client 端
下载Windows 端程序:http://tortoisesvn.net/downloads。执行下载回来的TortoiseSVN安装程序,进行TortoiseSVN 的安装。正确安装后,应该进行一次的重开机,以确保TortoiseSVN的正确无误。安装成功后,在档案管理员内按下鼠标右键,应该可以看到如右图所示:
大部分的TortoiseSVN的操作都是透过档案管理员及鼠标右键帱可以完成了。如果您之前使用过TortoiseCVS,应该会对这种操作方式感到十分亲切。
2. 使用checkout 获取开源软件的一个拷贝(Working Copy)
以获取项目最新的文件。当第一次获得最新Repository的文件时,用Checkout命令。(以后再获取最新文件时就不用Checkout了。而改用Update命令。)
具体操作:新建一个空的文件夹,右键点击它,可以看到TortoiseSVN菜单以及上面的SVN Checkout(也可以选择TortoiseSVN菜单下的Export...)。接着它会让你输入url,比如输入【迷宫探宝】的SVN地址是:
http://game-rts-framework.googlecode.com/svn/trunk/
其他选项不需要更改,Omit externals不要勾选,HEAD Revision选中表示最新的代码版本,接着点击OK即可将代码导出到这个目录中:)
3. 怎么样在Windows下面建立SVN Repository?
假设您的要放置Repository的地方是E盘。您需要先建立一个空的目录。以下面的例子而言,我们在E盘下面建立了一个名为svn_repo的目录。SVN并没有有限定Repository目录名称。您可以建立任何您自己喜欢的名称。但是,强烈建议勿使用非英文的档名(如中文或日文)。
4. SVN Update
使用SVN checkout获取一个“Working Copy”,比如F:\Project1,现在其他人已经对Repository进行了修改,我们想将别人的修改反映到我的“Working Copy”中,具体的方法是:在F:\Project1目录上单击右键,SVN Update。这时F:\Project1中的文件就是最新的版本了。
注意,如果当你的“Working Copy”中有被修改的文件,或者有被删除的文件,并且还未提交这些修改时,这些文件在执行Update过程中是不会被更新的。比如你修改了F:\Project1下a.txt文件,还未提交修改,那么,当你对F:\Project1进行Update时,a.txt文件是不会更新为Repository上的a.txt文件的。