有了Git之后按理说已经没有必要再用SVN,但是个别老土公司还是坚持用SVN的,所以不得不学习一下。
SVN的分支管理
在SVN中需要先建立一个主干分支(建立在服务器),这个主干分支就是代码管理的中心,其他所有协同工作的同学都需要从这个主干分支获取代码。一个完整的开发流程是这样的:
- 在服务器建立主干(俗称拉流)
- 开发同学A,B,C分别从主干分支获取代码
- A同学在本地改动了代码,经检查无误后,更新到主干分支
- B同学从主干分支拉取更新(A提交的代码),B做了一些改动后更新到主干分支
- C同学从主干分支拉取代码(A、B提交的代码),C发现A代码中有bug
- 在主干分支上回滚到A提交代码之前。
在SVN中,每次提交都会更新到服务器合并到主干分支,也就是说SVN只有一个代码版本管理系统——服务器的主干。
这种方式和Git是不同的,Git是分布式的,所谓分布式是指,不仅服务器端可以建立一个代码管理库,A、B、C三人也可以在自己的机器上建立代码管理库(在Git上是默认的)。这是SVN和Git最大的区别,这样的好处是,A、B、C可以在本地自己创建分支管理代码而不需要依赖服务器(其他人也会依赖服务器,这样导致每个人之间的工作会耦合在一起)来管理。一个简单而又常见的场景是:当前正在开发一个feature,这时候发现线上代码有bug需要紧急修复,如果使用Git的话,只需要在本地Check一个新的分支,修改错误,发新版,提交代码就行了。如果用SVN的话,想不出如何简单的解决这个问题。
SVN基本命令
对于代码管理工具,我一直倾向于使用命令,一是可以清楚版本管理系统究竟干了什么,二是不需要每次安装UI客户端,有的系统没有(免费)客户端可用,不同客户端操作方式也不一样。
- 导入项目
svn import http://svn.chinasvn.com:82/pthread --message "Start project"
- 导出项目
svn checkout http://svn.chinasvn.com:82/pthread
采用 export 的方式来导出一份“干净”的项目
svn export http://svn.chinasvn.com:82/pthread pthread
- 为失败的事务清场
svn cleanup
- 在本地进行代码修改,检查修改状态
svn status //默认当前 -v 选择版本
svn diff
- 更新(update)服务器数据到本地
svn update directory
svn update file
- 增加(add)本地数据到服务器
svn add file.c
svn add dir
对文件进行改名和删除
svn mv b.c bb.c
svn rm d.c
- 提交(commit)本地文档到服务器
svn commit
svn ci
svn ci -m "commit"
- 查看日志
svn log directory
svn log file
上面的命令已经涵盖了基本的开发命令,用过Git的同学都知道,在新建一个工程的时候最重要的是新建一个.gitignore
的文件,把不需要版本管理的文件(目录)忽略掉。在SVN中比较麻烦。
忽略干扰文件, SVN:IGNORE
在SVN中如果需要把文件从当前版本管理系统中移除,需要这么做:
svn propset svn:ignore *.class .
这条命令会把当前目录中的所有.class
文件忽略。如果要忽略的是文件夹,需要注意不能在文件夹名字前后加任何修饰符:
svn propset svn:ignore bin . # yes
svn propset svn:ignore /bin . # nope
svn propset svn:ignore bin/ . # nope
如果连续执行两个命令:
svn propset svn:ignore bin .
svn propset svn:ignore gen .
会发现一个奇怪的现象,SVN只把gen
目录忽略了,bin
目录还是会被SVN记录,这是 propset
命令设计的问题,这条命令每次执行都会覆盖前一次的结果。
解决这个问题的方式是使用 propedit
命令,这条命令会打开编辑器让我们编辑一个配置(类似.gitignore的配置)然后会忽略所有编辑的文件和目录。它有个前提要求,需要先指定一个编辑器(好麻烦!)。
> export SVN_EDITOR=vim //指定编辑器为vim
> svn propedit svn:ignore . //编辑配置
接下来会打开vim,配置参考:
.settings // .settings 文件
.classpath // .classpath 文件
.project // .project 目录
out // out 目录
这样操作之后,当前目录下的 .settings
、.classpath
和 .project
、out
目录就忽略掉了。但是其他子目录里面的这些文件却依然存在,显然不能把每个子目录都这么操作一遍。
其实到目前为止,上面的种种做法在使用的时候都是不现实的,好的做法还是回到 propset
命令,它其实接收两个可以解决当前问题的参数:
- -R 递归应用当前配置到每个子目录
- -F 指定一个配置文件
所以最终的方案是这样的,先建一个配置文件 .svnignore
,编辑配置文件,调用命令递归设置。
> touch .svnignore // 创建忽略配置文件
> vim .svnignore // 编辑配置
> svn propset svn:ignore -R -F .svnignore . //应用设置
注意每次编辑完 .svnignore
之后需要再次调用 svn propset svn:ignore -R -F .svnignore .
来应用配置。
参考文章: