最近使用了SVK,实现不同的SVN仓库之间的合并.
我们有2个Subversion服务器,USA和China的。双向同步,早上上班前把USA(美国同事的工作)同步到China,晚上下班后同步China(中国同事的工作)到USA。
步骤如下:
Step1: 找一台机器,安装SVN1.5和SVK2.2.,利用操作系统调度SVK命令:
SVK2.2从http://download.bestpractical.com/pub/svk/2.2.0/svk-v2.2.0-MSWin32-i386.exe下载。
Step2 :设置SVK仓库的根目录:
SET SVKROOT=c:/svk/ROOT
(可以把它写进系统环境变量,而且 以后可用svnserve -d -r c:/svk/root/ 命令把这个目录开放成:svn://localhost:3689,供离线浏览:)
Step4 :设置冲突解决模式:
SET SVKRESOLVE=y
(可以把它写进系统环境变量, 这样在同步的时候,遇到文件conflict,始终用source SVN repo的版本,这是一种能解决大部分冲突情况的方案,当冲突的时候,用自己的好嘞,实在不行,再行沟通,直到某个文件没有冲突为止,自动合并不能完全替代人际沟通!)
Step5: 映射Source SVN repo,Target SVN repo
svk depotmap --init
svk mirror http://svn.usa/projectx //prj-usa
svk mirror http://svn.china/projectx //prj-china
Step6 :同步source SVN repo.
svk sync //prj-usa
如果source SVN repo库实在太大,网速又慢,那么上面的步骤会难以忍受,那么可以使用:
svk sync -s HEAD //prj-usa
这样表示直接从source SVN repo的最新版本库开始同步下载。对target SVN repo也可以。
Step6 : 合并
svk smerge -B -C -I -s //prj-usa //prj-china>
%date:~0,10%-(%time:~0,2%-%time:~3,2%-%time:~6,2%)-merge.log
-B 表示从源版本库最早的版本号开始Merge(比如版本库的revision log从 1~10编号),那么加上这个参数则表示从版本1开始合并,从1到10的所有版本变化都将被合并到目标仓库。注意在合并的过程中,SVK会自动形成一新的系列版本号来对应编号1~10(比如3-13),但是这个新的系列版本号只是用来记载的,其中最大的版本号13会和原版本库中的最后提交 (Commited)形成的最大版本号(New merge ticket)对应, 下次合并的时候会从上次的最大版本号13而不是3开始。
-I 表示把源版本库的每个历史版本都分别做Merge,不使用这个参数则表明将整个版本库变化合并成单个变动,最终一次性地Merge到目标库;如把上面的3~13的所有变化都合并到目标库,而不是3合并一次,4合并一次。。。
一般情况下,为了避免过细冗余的版本操作历史记录,是不需要使用这个参数的。
-s 表示合并的时候,在合并前,先同步一下Source SVN repo,后并成功后同步一下dest SVN repo,这样在本地就保存着2个库的最新版本。
上面的 -C表示合并前比较一下2个库,看有什么差异,不使用这个参数就表示直接合并。
Step7: 调度(自动执行)
将上面Step6的命令分别写进批处理BAT文件,送到Windows 32 系统进行固定时间调度。
Windows XP来调度是正常的,Linux都不行的,不知道什么,可能Linux的任务调度中不能正确地初始化SVK2.0的Perl环境)
在Windows 2003 Server中调度会抱错:
The getpwuid function is unimplementd at D:/App/svk2.2/bin/svk line 142
那么将Perl脚本中:D:/App/svk2.2/bin/svk 142行~148行都删除就行了。
自动同步,还有一个就是对于源和目标仓库映射,如果改了用户的密码,必须手工输入一次,然后才能成功调度。
在合并的过程中如果遇到 下列错误日志:
Merge conflict during commit: File or directory '/html/index_hello.html' is out of date; try updating: resource out of date;
那么只能表明有些文件在合并到的时候source的比target的旧(比如一个文件先在source上commit,然后又到target上commit了一次,这样
source的时间比target晚),这样会因为这一个文件不能同步却导致整个同步过程会失败。
临时解决办法:手动Merge,先将target的merge到source,然后再执行Merge从source到Target。
彻底解决办法:在批处理中首先同步目标库。
SVK一个重要的缺点:
就是同步一个文件后会改变它的修改时间。这样造成不必要的混淆,这种情况下只能抛弃svk手工去做这些事情了。
其实利用 svn 命令的批处理+OS调度也能做同样的事情。