SVN中文手册
http://www.svn.org.cn/743.html
建议的SVN管理方式
这里只是个人建议
建立好分类目录
对于嵌入式开发来说,不单只有程序,还有程序对应的电路原理图,PCB、关键元器件datasheet、项目需求的资料,也应该放在一起。
尽量节省服务器空间
SVN的初衷还是管理文本文件(代码之类的)。它在服务器端,是用的差异存储方式,也就是相同的部分,只会存储一份,这样能节省整体占用的空间。
对于文本文件,它能很方便的分辨前后的差异,因此每次提交的代码,服务器的空间开销并不算大。
但是如果是文档资料,频繁的更改提交,对于服务器的存储空间开销来说,是一种负担,因为很多东西不是文本文件,它也识别不了其中的差异,只能当做新的内容存放,长此以往,会造成很大的空间浪费。
因此,对于文档资料目录,建议存放那些不经常改动的内容,或者说明性质的文本文件。
硬件目录
对于硬件来说,也要按PCB的不同进行分类,而且内部,只需要存储原理图和PCB。
使用AD或者PADS画图产生的所有中间文件,都不要上传到服务器占用空间。
程序目录
对于程序来说,也是根据每个程序,都有3个目录,分别是trunk、branches、tags
其中trunk为主干,日常的开发都在这里进行。
branches为分支目录,当多人协作的时候,经常用到分支目录。这里我们单人开发,可以不使用branches。
tags目录是存放稳定的版本,比如生产导入的程序,就要在这里对应一个tags目录。在下发程序之后,应该将trunk目录切一个分支到tags这里,并且命名、版本号,要和下发的程序一一对应。分支管理的操作后面会讲到。
tags目录的版本一旦生成了,就不要随意去改动。一个稳定的版本,系统是不推荐你修改它的内容的。
版本升级时,我们应该使用trunk目录的版本,再生成新的tags分支。而不是在原来tags目录的基础上进行修改
当某些客户有特殊需求时,也应该为它生成单独的tags分支。
程序的哪些内容不能上传
你可能是一个vscode爱好者,那么目录里面少不了相关的配置文件,.vscode,这里面是纯文本,上传到服务器并没有什么压力,建议保留。
我们知道C语言是编译型的高级语言,需要经过预处理、编译、链接,最后生成可执行文件,中间所有的C文件,都会生成对应的中间文件,这部分代码,一般在obj,或者output之类命名的文件夹里。他们占用的空间相对程序来说,很大很大。比如我这里,整个目录才26M,生成的文件就占了23M。程序才区区3M。如果你将这些文件全部上传到服务器,将会非常占用空间。并且因为它们是二进制文件,服务器是无法当做文本文件识别,而且每次编译生成的文件都不太一样,因此对服务器来说,将会有非常非常大的空间开销。
因此,这里要做的是文件忽略,将编译生成的文件全部忽略掉,或者将output文件夹递归忽略。文件忽略操作后面也有讲到。与这个相似的,还有一个listings文件夹,也可以忽略掉。
跟工程有关的文件,建议不要忽略,因为这里保存了很多keil里的设置选项。但是也不要频繁提交,如果有设置上的更改,比如目录结构变了,头文件包含变了之类的,建议提交一次。
在本地目录熟悉SVN操作
在正式使用SVN之前,建议先在本地建立一个目录,模拟服务器端,熟悉基本操作
任意新建一个文件夹,右键在此创建版本库
你现在拥有了自己的第一个SVN仓库,建议同时创建目录结构。这里注意要复制一下这个URL,等会要用。
版本库创建好之后,内部是这样的
然后再创建一个目录,在其内部svn检出
输入刚刚复制的URL,就相当于建立了客户端和服务器的联系。
可以在这个基础上,先熟悉基本的操作。
日常操作
常规操作
客户端的安装和汉化
在官网下载安装包和汉化包
https://tortoisesvn.net/downloads.html
默认安装即可
项目检出到本地
检出,checkout,就是从服务器下载代码到本地
先找服务器管理员索要账号密码和项目URL
在任意目录下,右键检出(checkout)
将项目URL粘贴进去,其它全部默认
用户认证
客户端首次使用,会要求输入用户名密码,这个找服务器管理员索要
用户认证注销
如果电脑上已经登录过其他用户,并且保存了,可以注销登录
检查修改
此处我修改了两个文件
本地修改过的文件,会有红色感叹号,表示和服务器上的版本有差别
如果修改的文件比较多,可以右键检查修改,查看当前修改了哪些文件
并且可以打开文件对比差异,查看改动的细节
提交代码
commit,提交,把本地的修改提交到服务器,右键提交即可
新增文件
如果新建了一个文件,并写了若干文字
可以直接提交,客户端会识别到没有添加到版本控制的文件,并自动添加后提交到服务器
如果你要增加的文件比较多,你准备一项一项的确认后,再一次性提交,就可以使用添加功能
这里我又新建了一个文件,右键增加
软件会自动识别没有被添加的文件
没有提交到服务器之前,会显示+号
撤销增加
如果此时后悔了,并且暂时还只添加到了本地,还没有提交到服务器,可以在文件上右键撤销添加
撤销修改
如果某个文件被你修改掉了,此时还没有提交到服务器
你希望让它恢复初始的样子,可以使用菜单里的SVN还原
勾选文件并执行后,会恢复到当前版本最初的样子
撤销提交
如果你修改并提交到服务器后,发现修改的文件有问题,想撤销提交到服务器这一步的操作,是做不到的,服务器会把每一次提交都记录下来,但是有办法恢复到之前的版本
比如我这里,提交的代码是有BUG的,但是服务器已经记录了新的版本
可以在最新版本上,右键,复原此版本做出的修改
还原后,刚刚更改的文件,会变成没有修改之前的样子,此时再提交一遍即可
此时查看日志可以发现,新版本,已经把老版本覆盖了
SVN服务器会把所有的提交都记录,你如果提交了错误的代码, 只能把先保证版本是最新的,然后把修改后的文件恢复到上一个版本的样子,之后再提交,用新版本去覆盖错误的版本,而不能希望通过版本回退解决问题。
如果你发现连续几个版本,都是有问题的,可以直接复原到之前的某个版本,再进行提交。
如果出现冲突,可以参考后面冲突处理的章节。
删除文件
本地纳入版本管理的软件,可以用delete或者右键删除后提交
也可以用SVN菜单的删除后提交,显示的状态会不一样,但是提交后结果没有差别
文件改名
两种方法,直接改,改完提交
第二种,右键改名后提交
更新
update,更新,从服务器获取最新文件
如果是多人合作项目,那么别人随时可以上传代码到服务器,我们本地的不一定是最新版本
我们在提交自己的代码之前,就要先更新,保证自己写的部分,和别人没有冲突
如果有冲突,参考后面的解决冲突章节
查看日志
版本库浏览
可以浏览到你项目URL在服务器上某个版本的全部内容
左边是目录结构,右上是版本号,head就是最新版本
可以切到历史版本,去查看文件,这里的文件都是可以直接打开看的
版本回退
如果当前工作出错了,可以回退到之前提交的版本,测试程序是否有同样的BUG,以此来确认BUG是刚刚修改过的代码导致的
更新至版本
版本号可以去日志里面去查看
此时代码将会回退到指定的版本。
这个功能只是让你本地的代码恢复指定版本,注意,不建议在这上面修改后,直接提交。
比如我这里修改后直接提交
会提示报错,因为当前工作的版本,并不是最新的版本
因此需要先更新到最新的版本
软件会自动将你修改后的代码,和新版本合并,合并后的代码,也不能直接提交,因为很有可能会出现冲突,因此先检查,再提交。
查看文件差异
接上一步,合并后自动弹出提交的对话框,此时双击打开文件,查看前后差异。
平时提交代码之前,记得多看看文件的差异,以免遗漏一些问题
可以看到这是我刚刚修改过的,确认无误后,直接提交
文件忽略
如果希望项目下的一些文件,不要被添加到版本管理中
比如我们程序编译链接生成的中间文件,每次编译后可能都不一样,并且是二进制文件,如果每次更新都提交,将会给服务器空间造成巨大的压力
因此推荐那些编译、链接产生的中间文件,包括AD等一些软件产生的中间文件,不要纳入版本管理
比如我这里新建了一个output文件夹,用于存放软件编译产生的中间文件
在希望忽略的文件或者文件夹下,右键,增加到忽略列表,recursively就是递归的意思,会把该目录下所有文件全部添加忽略,这样会比较彻底
如果是之前已经提交过的文件,添加忽略后,还要提交修改到服务器。
如果希望忽略某一后缀的全部文件,还可以这样操作
忽略之后,怎么重新纳入版本管理,还是老地方,选择增加,或者从忽略列表删除
解决冲突
冲突的产生,是因为和别人修改了同一位置的代码
比如我张三和李四,都修改了这里的main.cpp文件
而李四抢先提交了,我并不知道
那么我提交的时候,系统就会提示我的副本不是最新的,需要先更新
在更新过程中,系统会提示产生了冲突
为什么会冲突,这里对比一下代码
这里远程文件,就是服务器那边的代码,同一位置的代码,改成了lisi test
而本地文件,我们修改的部分,是zhangsan test
相同位置代码不同,因此导致了冲突(这里之前版本就有,这里只是修改了打印的内容)
与此同时,工作目录下多出了3个文件
其中R29代表服务器最新的代码, 版本号为29,R28是我本地的代码, 因为更新之前版本号是28
我们用beyond compare或者winmerge进行对比,发现R28和R29的差异,就是之前在SVN merge里面看到的差异
我们再把剩下的两个main文件打开
发现mine就是我本地修改后的文件,main.cpp是软件自动帮我们把差异化的部分集中起来了,方便我们进行阅读修改
如果我觉得我的代码更好,那么就把无关内容都删除掉,重新提交即可
冲突的内容修改完毕后,需要告诉软件,右键解决
直接提交即可
新建分支
svn的存储结构一般建议在项目根目录下建立trunk、branches、tags这三个文件夹。
trunk用于平时的正常工作,branches用于存放各种分支,tags用于存放各种发布版本或某状态的快照。
tags本质上和branches是一样的,都是一种分支,只是习惯上branches下面的东西会被修改、合并,而tags下面的东西则作为某阶段的状态保存不动。
一般tags下面经常放的都是各个发布版本,如Release0.91、Release1.23等
此时,branches分支还是空文件夹,因此先建立新的分支
我们从主干trunk创建分支,右键trunk目录,选择分支(branches)、标记(tags)
这里要修改的内容比较多,要看仔细。
我演示的是从trunk目录创建分支,创建分支实际上就是复制,这里希望把trunk复制到branches目录下,就要右键trunk去创建分支
至路径,这里是要进行更改的,改到branches目录下,并且还要指定一个新的文件夹名字用来保存分支
然后写上日志,用最新版本创建分支
这里提示已经创建完成,其实只是在服务器端完成了复制
在项目目录下,或者branches目录下,点击更新,分支文件才会复制到本地
可以看到该目录下,保存的是trunk目录下的所有内容
从此,trunk和分支,就分开了,trunk那边的提交,不会影响分支这边,分支这边的提交,也不会影响到trunk
我们在分支上进行开发,比如这里新建一个文件,这里提交的时候会发现目的地并不是之前的主干trunk目录了。
分支删除
两种方式,我现在已经有一个分支了
直接原地删除后提交即可
也可以通过版本库浏览器进行删除
分支切换
这个功能不建议使用,需要用到哪个分支,就把哪个分支checkout到本地,然后修改后提交即可
SVN与GIT不同的一点就是,SVN可以checkout很小一个目录,但是GIT只能checkout整个程序库
比如,我可以把分支01,直接checkout到桌面进行工作
修改后提交,可以看到服务器端已经更新了
分支合并
为什么要进行分支合并
比如当前我在trunk目录进行开发,此时我需要进行大量的代码修改,而另一个同事正在补BUG,我们都需要往trunk目录频繁提交代码,此时可能会经常需要去解决冲突。
这时就需要从trunk切出一个分支,我自己在上面一边写,一边提交,不会影响到同事的工作。
在我的功能修改完毕以后,在把分支合并到主干即可。
当然,在我几天时间修改代码期间,可能主干程序已经修改了无数版本,有一些我做了重大修改的文件,可能都已经删除了,那我几天的工作岂不是白费了。
这就要求每天都要把主干目录合并到分支,解决了冲突之后,继续在分支上开发,避免做很多的无用功。
这里就两种情况,都是非常重要的
- 分支合并到主干
- 主干合并到分支
我这里切出来一个分支,并进行了一些修改后提交
提交成功,在主干trunk目录右键,合并
这里两个地方需要修改,第一是从哪里合并过来的,第二是哪些修改过的版本需要进行合并,这里一般选择所有版本
看到提示信息,已经合并成功了。
再讲一下trunk合并到分支,这里操作其实差不多,先将trunk更新到最新版本,然后在分支上右键合并,注意这里是去分支那边右键点击合并。
你希望合并到哪,就去哪里右键点击合并。
代码贮藏
shelve,贮藏
如果工作目录下,代码已经修改了很多,但是还没有改完,所以没有提交
这是突然报告了一个紧急BUG,需要立即进行修复
我们需要把工作目录切换到没有问题的版本,又不希望本地工作内容的丢失,就可以用代码贮藏功能
比如我这里修改了两个文件
先把代码贮藏起来
这里给贮存工具架起好名字,因为可能贮存了好几个不同时期的代码,需要进行区分
此时发现文件已经恢复到之前的版本,就可以在上面进行开发了
工作完毕后,希望恢复贮存之前的文件,可以取消贮藏
选择之前贮藏时设置的工具架进行恢复。
如果有多次贮藏,可能会产生不同的工具架,和不同的版本号,恢复贮藏的时候要注意。
系统默认软件的调整
如果你安装了一些软件,比如winmerge、beyondcompare之类的软件,系统设置可能会默认去调用外部的程序,这里还是建议默认使用软件内部自带的软件