以下仅用于个人建议。
一、 svn权限
- svn用户
- svn目录各层次
两者在svn工具里权限设置及其方便简单。
经验:
- 权限设置太细。svn管理会太繁琐;svn使用者遇到项目设计问题很难debug。
- 极其敏感的公共文件,设置可写权限即可。
二、 svn分支
- trunk
- tags
- branches
这三个基本够用了。工作流程有几种,个人推荐
trunk是较稳定版本;branches稳定后merge到trunk,这里只会出现因为merge导致的错误或者系统级仿真错误。一般不会出现编译错误。
branches是成员的维护版本;随便提交,允许出现编译错误,不会影响其他成员。
tags是稳定版本,跑过全部测试集。
三、 项目中遇到的问题总结
基本原则:
- svn使用者,尽量不受权限束缚。可以灵活处理各种项目问题,以避免出问题,只能求助svn管理员。
- svn tags必须保证稳定性。方便项目设计的回顾。
- svn分支,做到最简单直接有效。svn制定的规则越多,管理越混乱。尽量使用svn官方推荐流程,毕竟都是通用的。之前项目,把svn很多行为都做了封装,我认为缺点是svn使用者解决问题思路极其受限,完全依赖svn管理员;对svn使用者和管理员都不是好事。
svn内容太大,怎么解?
svn内容太大,危害就是svn up、svn co、svn st的过程缓慢。
解决思路:
非常稳定的设计(比如购买的IP),放在trunk目录以外。
例如:- project
- trunk
- tags
- branches
- stableVerilog
- stableVerification
- project
svn使用者第一次需要checkout整个目录。
svn co svn://192.168.1.1/project project
- svn使用者第二次以及之后的svn操作,比如svn update project/trunk。不需要再svn up project。解决svn内容太大导致svn up太慢的弊端。
svn的trunk经常不稳定,怎么解?
项目更新,都在trunk分支上。但是不能保证每个人提交的内容,在trunk下都能稳定跑项目仿真。
思想,仍然是使用分支merge操作。
解决思路:
- svn tags的意义,更多是为了提供一个正式版本,为了FPGA仿真、R0signoff、R1signoff等。
- svn tags还有一个重要意义,比如每周打一次tag。以便trunk跑不通的时候,知道系统项目的哪个版本是最近稳定的。tag的名称,可以是日期+版本号的形式。
例如;
svn cp svn://192.168.1.1/project/trunk svn://192.168.1.1/project/tags/20170909_r211
- trunk版本,只有打tag的时候,才是有意义的。trunk版本是大家共同维护的主干分支,所有代码都要及时提交至这个主干分支里;不必强求,每周打tag之前把自己代码全部提交,不可能做到,只求自己代码稳定时,就更新至trunk分支里。
- svn使用者,仿真使用的不是trunk最新版,是在branches里。同时,是基于最近稳定的tag版本。
例如;
svn cp svn://192.168.1.1/project/tags/20170909_r211 svn://192.168.1.1/project/branches/qilei/20170909_r211
- svn merge命令是正规方法(之后再讲这个操作流程)。有些人会陌生恐惧,其实多做几次就理解消化成习惯了。当然,还有最原始的办法可以推荐(这个最原始的方法,就是svn merge的思想,即diff and apply)。
例如;当svn://192.168.1.1/project/branches/qilei/20170909_r211,该分支提交完成(重点,已提交),并顺利通过仿真后,
#检查自己的修改与trunk分支的代码区别,参数--summarize,只会报告不同的代码。
svn diff svn://192.168.1.1/project/branches/qilei/20170909_r211 svn://192.168.1.1/project/trunk --summarize
#更新trunk版本至最新版
svn up project/trunk
#把自己负责的代码,拷贝到
svn cp project/branches/qilei/20170909_r211/xxx.v project/trunk/xxx.v
#最后,在project/trunk里查看所有更改
svn diff xxx.v
#本着对自己对他人负责的态度,跑一遍project/trunk的仿真;然后提交至trunk分支,顺便提交一个系统最近稳定的tag版本
svn ci xxx.v -m "commit my code to trunk"
svn cp svn://192.168.1.1/project/trunk svn://192.168.1.1/project/tags/20170909_r258
#至此,已经完成一个循环
svn cp svn://192.168.1.1/project/tags/20170909_r258 svn://192.168.1.1/project/branches/qilei/20170909_r258
svn merge
这部分是转载的。
细节就以下几点:
1. trunk到branches的merge;branches到trunk的merge。
2. merge时,一定要指明版本号。否则merge结果是最新版本号,即trunk和branches的代码都是一样的;这就没有意义了。
3. svn冲突conflict的解决方法,选择postpone方式,代码确认后。svn resolve xxx.v --accept working
,通知svn,已解决冲突;然后正常提交即可。
4. svn merge取消方法
svn diff
#可以看到当前merge后的改动信息,其中一个改动是增加了一个svn:mergeinfo属性。
#svn merge操作出现问题,想取消这次merge。
svn propdel svn:mergeinfo
SVN分支和合并的简单例子 尽管svn没有作强制要求,但是一般svn版本库目录建议创建trunk、branches和tags三个目录。 在实际操作时,trunk主干版本要时刻保持干净,即随时可以基于这个版本进行修改并将应用部署上线。branches是分支目录,存放并行开发的项目代码,因为分支是主干的廉价拷贝(相当只是提交了一次主干版本,增加了一个版本号,并没有取出版本库作镜像拷贝),所以你可以放心建立很多分支版本。不过Subversion不支持跨版本库的拷贝,当使用svn copy时你只能在同一个版本库内操作。tags目录存放trunk某个的快照,比如说release-1.0即trunk处于1.0版本时的快照。
使用svn来作团队的代码管理,那么分支和合并将是非常常用的操作。下面是一个简单的示例。
1. 创建分支。这里假设你要负责一个叫theme的项目,分支号1.7.2。
#这里的localhost是svn服务器地址 svn copy -m "1.7.2 - theme" svn://localhost/www/trunk svn://localhost/www/branches/branch1.7.2-theme svn co svn://localhost/www/branches/branch1.7.2-theme
2. 从trunk中merge到分支。忙了一个星期终于开发完了,但是开发期间trunk版本有过改动,部署上线前你需要合并trunk的代码。
#branch1.7.2-theme是分支目录,注意不可以进到分支子目录 cd branch1.7.2-theme
#前面的12972是开分支之前trunk的版本号,后面的12991是merge时trunk的版本号 svn merge -r 12972:12991 svn://localhost/www/trunk
如果有冲突选择p(postpone),merge完了之后使用svn st|grep ^C查看冲突文件,然后比对修改冲突文件。解决冲突后再check in ,信息写上执行的merge操作。 svn ci -m 'svn merge -r 12972:12991 svn://localhost/www/trunk'
3. 从分支merge到trunk。上线测试完毕,你很幸运,一切都如预期正常,这时就要将分支回归trunk,将trunk更新到最新。
#先从trunk checkout一份新鲜的代码,然后cd到该版本目录下 svn co svn://localhost/www/trunk
cd trunk
#12973是分支开始的版本号,13006是分支结束的版本号 svn merge -r 12973:13006 svn://localhost/www/branches/branch1.7.2-theme
如步骤2一样解决冲突,解决冲突后再check in,信息写上执行的merge操作。 svn ci -m "svn merge -r 12973:13006 svn://localhost/www/branches/branch1.7.2-theme"
冲突的处理方式
(p) postpone – mark the conflict to be resolved later //让文件在更新完成之后保持冲突状态。
(df) diff-full – show all changes made to merged file //使用标准区别格式显示base修订版本和冲突文件本身的区别。
(e) edit – change merged file in an editor //用你喜欢的编辑器打开冲突的文件,编辑器是环境变量EDITOR设置的。
(r) resolved – accept merged version of file //完成文件编辑之后,通知svn你已经解决了文件的冲突,它必须接受当前的内容—从本质上讲就是你已经“解决了”冲突。
(mf) mine-full – accept my version of entire file (ignore their change//丢弃新从服务器接收的变更,并只使用你查看文件的本地修改。
(tf) theirs-full – accept their version of entire file (lose my changes)//丢弃你对查看文件的本地修改,只使用从服务器新接收的变更。
(l) launch – launch external tool to resolve conflict//启动一个外置程序来执行冲突解决,这需要一些预先的准备。
四、 疑问?
svn使用者未及时提交代码至trunk分支,怎么办?
svn使用者在分支branches仿真稳定后,就应该提交至trunk;如果trunk仿真通过,branches就使用最新的环境。这个过程如上介绍,没什么复杂和时间花费。
提交代码至trunk后,在trunk里仿真不通过,怎么办?
找错误负责人,赶紧debug。
因为提交的流程,可知trunk版本,是较为稳定的。因为每个人是仿真后提交的,所以错误都是容易马上解决的。
即便一时难以解决,自己仍然可以使用原始branches分支,继续维护代码。
别人发现bug后。自己更新代码,要在对方branches里提交。尽量不在trunk里直接更新,避免trunk不稳定。
svn使用者流程总是不清晰,怎么办?
总结常见FAQ,发布在公共文档里。
svn备份
每周打tag的同时,做一个备份。备份利用覆盖方式即可,不需要一周独立一个备份;这样可以节省硬盘空间。
svn备份一般采用三种方式 - CSDN博客
http://blog.csdn.net/beyondlpf/article/details/54138865
一个项目是多个svn仓库,还是一个svn仓库管理?
因为版本号的原因,相关性较大的事项,作为一个svn仓库管理方便。比如设计与验证。
相关性较小的事项,作为另外独立的svn仓库管理方便。比如设计和验证/RAM-io-stdcell-analog库和综合和时序分析和LEC。
因为项目数据太大或者目录层次太深,导致svn up和svn st等操作响应时间太长,怎么办?
- 前期合理规划;经常修改的代码,放在一个目录里,该目录下的文件数目尽量少,即可解决。
- 使用固态硬盘,作为本地working copy。经实验,从一分钟可以达到几秒。
- 如果出现误操作,导致规划不合理,可以利用彻底删除svn服务器文件的方式,解决。