版本控制 - SVN
一、在linux下安装SVN:
1、Ubuntu:
apt-get install subversion
2、CentOS:
yum install subversion
————subversion已经内置了客户端还是服务端。
二、服务端和客户端命令介绍:
服务端命令:
svnserve - 控制svn系统服务的启动等 svnadmin - 版本库的创建/导出/导入/删除等 svnlook - 查看版本库的信息等
客户端命令:
svn - 版本库的检出/更新/提交/重定向等
三、启动服务:
启动svn服务:一个完整的SVN服务会有一个服务端和多个客户端。客户端可以在任意客户端访问。
svnserve -d -r /svn/ //这种方式比较合理,可以设置多个版本库而不需要不断分配端口号。检出的时候,根目录相当于是svn
四、版本库的创建和删除:
创建版本库blog:
mkdir /svn svnadmin create /svn/blog //创建版本库blog,请注意实际的svn服务根目录是不是/svn
删除版本库——如果需要(这就是linux的rm命令):
rm rvf /svn/blog //请注意实际的svn服务根目录是不是/svn
五、版本库的权限配置:
在项目仓库的conf文件夹之下,修改配置。即每个仓库都有自己的配置文件。
authz - 配置用户组以及用户组权限 passwd - 配置用户名和密钥 svnserver.conf - 配置默认权限、权限配置文件及密码配置文件
打开svnserver.conf,如下:
——以上为:默认设置。如图,我们把前面的#拿掉即可。
anon-access:无账号密码用户为read,即更新。假设,想要让无账号密码的用户什么都做不了,则把read改成none即可。
auth-access:有账号密码的用户为write,既可以更新也可以写入。
password-db:指定密码文件的路径。
authz-db:指定设置用户的文件路径。
我们再来看下passwd的文件,设置两个用户名和密码即可,格式为[username] = [password]:
配置好了用户名和密码之后,我们就可以去authz里面分组和配置权限了。
打开authz,配置:
[aliases] - 别名配置,很少用到。
[groups] - 分组配置,上图中pm组有chenweifeng,dev组有linfeng、xingjingtao、xuhezhuo
[blog:/] - 对blog版本库设置:pm组有r的权限,dev组有rw的权限。也可以对每个用户进行权限设置。
————最后,如果要对所有成员设置,只要左边是*即可。
// 关于svn的重启:
当我们修改了配置文件后,我们需要重启:
//查看svn服务详情 ps aux | grep svn //将svn服务强制停止 其中790为svn服务的ID号,-9是kill的参数 kill -9 790
或者用:
killall svnserve
再运行:
svnserve -d -r /svn/ //进行启动服务
六、首次导入、检出到客户端和创建trunk/branchs/tags目录
1、从服务器检出资源到本地:——请注意,我们是把整个仓库blog检出,blog里面有trunk、branchs、tags。而如果是测试环境,正式环境checkout,则需要检出的是仓库blog下的trunk。即:开发的时候,需要检出主干和分支代码,而正式环境、测试环境,只要检出主干即可。需要的时候svn up一下代码即可。
svn checkout svn://xx.xx.xx.xx/blog /Users/linfeng/svn/blog --username=linfeng --password=123456 //本地代码检出
svn checkout svn://xx.xx.xx.xx/blog/trunk /Users/linfeng/svn/blog --username=linfeng --password=123456 //正式环境、测试环境检出
—— 此时svn的地址,就是svn服务根目录地址之后开始的。一般情况下,仓库命名方式是域名,不会只是个blog。
2、客户端创建trunk/branchs/tags目录并提交 - - 首次检出需要创建trunk/branchs/tags目录,如果是已经有了,你就正常使用就好了。
//切换到本地客户端,本例子即第一步中的/Users/linfeng/svn/blog cd /Users/linfeng/svn/blog //切换到本地仓库目录下 mkdir trunk branchs tags //创建3个目录 svn add * --force //加入版本库 svn commit -m '创建trunk/branchs/tags' * //提交
3、第一次初始化导入(首次上传):-centOS7有防火墙问题,请添加安全组和防护墙的端口。
svn import /var/www/blog svn://127.0.0.1/blog/trunk --username=linfeng --password=123456 -m "初始化导入到主干版本" //本例子在服务器上导入,所以源没有写IP
——导入的时候,是导入到blog/trunk之下的。web目录检出的时候,也是检出trunk目录的。
—— 注意,此时svn的根目录地址,不是服务器的根目录,而是你启动服务的地址(如/svn)之后开始算的。
4、本地更新:
svn up //更新本地代码
七、常用的命令————请注意当前所在目录
1、svn up:更新工作副本(即从服务器下载最新的)——在提交前需要先uodate,不然别人的会被你给覆盖的。第一次使用checkout,后面都使用update
svn up * //需要先切换到该目录下
2、svn add:添加版本控制文件 ——有新增文件/文件夹的时候,需要先add,表示把该文件添加到版本控制里边。不然commit的时候无法传上去。
svn add js '增加js目录到版本控制' svn add * --force //--force表示需要扫描已加入版本库的文件夹,因为里面可能还是有文件未加入版本库
3、svn commit:提交修改到服务器 ——无添加文件,只是修改了文件,直接commit即可。备注为必须参数
svn commit -m "修改了main.m文件" index.html //同步index.html到svn服务器 svn commit -m "修改了main.m文件" * //提交版本控制里面改动过全部文件,有新增文件的时候需要先add
4、svn delete:从版本库中删除文件或目录————一般会配合commit(ci)使用
svn delete 文件名 //一般delete后会commit
5、svn st:查看版本库当前状态 ——查看当前本地版本库库做了哪些修改
svn st //会列出增加了哪些东西,删除了哪些东西。
6、批量标记已删除文件加入版本——本地手动删除文件时候(非使用svn delete删除的),会在本地版本库标记为!,需要改为D,以下命令就是批量将!改为D,则提交的时候,服务端也会删除该文件
svn status | grep ! | awk '{print $2}' | xargs svn delete
—— 如果使用svn delete删除的,则svn st,会显示状态为D,手动删除的,则会显示状态!,需操作后才会进入版本库
———— 使用频率不那么高的命令学习:
svn diff * //比较所有文件的差异 svn diff -r 1:3 index.html //比较index.html这个文件,版本1和版本3的区别 svn mkdir js //创建目录并增加到版本控制 svn cat svn://IP/index.html //不检出工作副本,直接查看svn服务器上指定文件 svn revert --recursive * //批量还原所有文件,还原到与当前版本一直 svn revert index.html //还原index.html与服务器一致
冲突的种类和原因:
二进制冲突:A、B都更改了同一处代码,A提交的之后,B在未更新工作副本的情况下也提交了。svn服务器认为B是不知情了。所以提示冲突。解决方法:提交前先更新。
树冲突:图片之类的(非html/css/js之类的),无法精确到某行的冲突。
冲突的解决:
建议推迟处理,那么冲突部分的代码,会保存到B的机器上。保存的是两个版本的都代码都有。保存后处理如下:
以下两种方式选择一种:
vim index.html //这种方式进行编辑并保存。 svn resolve index.html //会出现冲突出现时候的选项,这次你就可以选择商量后的结果。而不需要再推迟(P选项)。
使用vim方式处理后,需要告诉svn,index.html的冲突解决了:
svn resolved index.html
然后提交给服务器:
svn commit -m '处理了冲突' index.html
————当然,修改的时候,你也可以锁定该文件,让别人改不了,改完了后再解锁:
svn lock index.html //锁定index.html,别人无法做修改 svn unlock index.html //解锁index.html,别人又可以修改了
以下为一些文件日志查看方式:
svn ls --recursive //递归列出当前目录下处于版本控制的所有文件。 svn st //列出工作副本中的文件/目录的状态 svn log //查看提交日志(也就是commit -m后面的参数) svn info //工作副本及文件夹的详细信息
八、创建分支版本库:使用svn copy命令 ——注意:其实一开始就需要创建trunk、branch和tag,tag是用来已发布版本的代码备份的。
1、创建分支版本
//本地的仓库
svn cp svn://xx.xx.xx.xx/blog/trunk svn://xx.xx.xx.xx/blog/branchs/blog2.0 -m '创建2.0分支' //这时候操作的是服务器的分支,本地需同步
svn up //更新本地,需要先切换到本地仓库目录
2、把工作目录转移到分支或转回主干:
svn switch svn://118.xx.xx.xx/blog/branchs/blog2.0 //转移到分支 svn switch svn://118.xx.xx.xx/blog/trunk //转移到主干
九、合并分支
情况一:合并一个分支到主干
// 1、切换到本地分支库,查找创建时候的版本号。 cd /Users/linfeng/svn/blog/branchs/blog2.0 //切换到分支目录 svn info // 获取分支url svn log --verbose --stop-on-copy | tail -10 //获取分支创建时的版本号(r3),位于最下方 // 2、切换到主干目录,获得最新版本号,进行合并并提交: cd /Users/linfeng/svn/blog/trunk //切换到主干目录 svn up //获得最新版本号,(r5) svn merge -r 3:5 svn://118.xx.xx.xx/blog/branchs/blog2.0 //合并3-5的版本到主干版本上 svn commit -m "提交合并分支" * //提交合并分支
————至此,合并分支到主干道成功,你可以在本地进行up,则可以更新最新的代码库。
情况二:合并分支到主干 =>其实就是情况一反过来即可
// 1、切换到分支版本库 cd /Users/linfeng/svn/blog/branchs/blog2.0 // 2、进行合并主干版本到分支 svn merge [-r M:N] svn://118.xx.xx.xx/blog/trunk
十、svn自动同步到web目录。
第1步:—— 此时检出的代码是主干trunk的,所以主干有commit的时候,才会自动同步。
svn checkout svn://127.0.0.1/blog/trunk /var/www/blog -m "检出代码"
以下更贴切:
svn checkout svn://127.0.0.1/domain.com/trunk /www/wwwroot/domain.com --username=zhangsan --password=mima
第2步:进入svn的项目目录,然后进入hooks目录,执行:
cd /svn/blog/hooks //进入服务器配置目录
vim post-commit //编辑文件
然后在post-commit文件里面添加以下内容:
#!/bin/sh #设定环境变量,如果没有设定可能会出现update报错 #设定语言,根据系统语言设置,如果是GBK就设置为 LANG=zh_CN.GBK export LANG=en_US.utf8 SVN_PATH=/usr/bin/svn WEB_PATH=/var/www/blog $SVN_PATH update $WEB_PATH --username 'linfeng' --password '123456' --no-auth-cache
第3步:赋予post-commit权限:
chmod -R 755 post-commit
————那么当你出现任何提交,都会自动同步到web目录
2)版本库的精简和丢弃:
3)版本库迁移与重定向:
迁移:停掉svn服务,直接把整个版本库压缩成zip包。然后放到新的服务器上,新的服务器启动即可。 <<== 方式非官方
重定向:——往后svn客户端就和新的svn服务器进行通讯
// 版本库更换服务器的时候,需要进行本地仓库的重定向到新的svn服务器
cd /Users/linfeng/svn/blog svn switch --relocate svn://111.0.0.0/blog svn://111.1.1.1/blog
十一:tags目录的使用:
svn copy svn://118.xx.xx.xx/blog/trunk/ svn://118.xx.xx.xx/blog/trunk/tags/v1.0 //备份当前已发布的trunk的代码,作为阶段性代码保存
十二:测试环境和正式环境
测试环境:checkout出trunk的代码,并在钩子里面设置有提交自动同步到该目录下
正式环境:checkout出trunk的代码,只有有需要的时候进行update即可。
————————— 总结 ————————————
// SVN 常用命令行-客户端
1、首次从服务器检出:
svn checkout svn地址 本地路径 --username=linfeng --password=123456
2、更新本地代码(从服务端更新最新代码)
svn up
3、添加所有变动到版本库(修改过的添加到本地版本库)
svn add * --force
4、本地版本库删除某文件
svn delete 文件名
5、提交所有更新到服务端(需要先add和delete)
svn ci -m "更新了个人文件内容" *
6、查看本地版本库当前所做的修改状态
svn st
// 基础知识
1、branches和tag都是仓库(服务端)的操作,操作完后可update到本地
2、暂存(shelve):突然临时修改BUG,而原先的功能没写完。就把原先修改的进行暂存不提交,等紧急bug提交了后再恢复。
3、选择add working copy:即添加到版本库。对应命令行为svn add *,增加新的文件的时候,会用到这个。
4、版本回退,是本地代码才有版本回退的说法,指的是本地的代码需要回退到什么版本号然后继续修改。服务端仓库的版本,是一直往上叠加的。
// 关于仓库管理(多人协作)
1、建立仓库,个人的分支代码向仓库同步(个人开发环境也在服务器)
2、总开发环境设置钩子,有提交则向仓库自动拉取代码。
3、测试环境手动拉取代码。
4、正式环境手动拉取代码。
有仓库在那里,拉取到测试、正式环境都好说。
————占位符