问题的产生:
对于采用Copy-Modified-Merge方式的版本控制系统,冲突的管理和解决是非常重要的。
目前公司的一个项目由于系统的版本升级,系统的源代码在开发过程中有大量的文件重命名操作,原有的CVS不支持文件重命名,每次都需要删除原有文件,再重新导入新的文件,导致文件更改历史丢失;为了解决这个问题,我们把版本控制工具从CVS改成了Subversion,客户端从TortoiseCVS改为了TortoiseSVN;由于TortoiseCVS和TortoiseSVN的使用极为相似,因此转移后大家在使用上并没有遇到什么问题——除了对文件冲突的解决方式;
问题的详细分析:
在文件的合并发生冲突时,冲突文件主要有以下几个版本:
Base:自己的工作复本中该文件的原始版本
Mine:自己的工作文件
Theirs:版本库中的最新文件
Merged:在TortoiseSVN中自动合并后的文件,在该文件中,用如下方式标识了文件中发生冲突的部分(这种方式似乎是Unix世界的通用方式?):
<<<<<<< filename
your changes
=======
code merged from repository
>>>>>>> revision
在 TortoiseCVS 中,对冲突文件的合并是用Mine和Theirs进行比较进行的,合并后的文件即作为工作复本中冲突已解决的新文件;而在TortoiseSVN中,对于冲突的文件(比如ConflictFile.txt),会自动生成以下几个文件:
ConflictFile.txt.mine(自己的工作复本Mine)
ConflictFile.txt.rBaseRevision(原始版本Base)
ConflictFile.txt.rNewRevision(版本库中的新版本Theirs)
ConflictFile.txt(合并后的文件Merged)
TortoiseSVN 的冲突解决需要对以上文件进行比较合并,最终将所有的修改都合并到Merged版本中,然后将冲突设置为已解决;但是由于工作复本、版本库的新版本以及合并的目标分别存储在三个文件中,因此TortoiseSVN的冲突解决就需要使用支持三向比较(3-Ways)的比较/合并工具,比如TortoiseSVN内置的TortoiseMerge(免费),或者Araxis
Merge(收费);原来我们在TortoiseCVS中使用的Beyond Compare就无法使用了,因为BC只支持对两个文件进行比较,在TortoiseSVN中使用Beyond
Compare作为合并工具的话,就还需要手工作很多工作——大家就是对这一点非常不适应。
问题解决方案:
1.编写如下的批处理文件(注意将Beyond Comare的路径改为实际的路径):
"D:\Applications\DevTools\BeyondCompare2\BC2.exe"
%1 %2
Del %3
Del %4
Del %2
Copy %1 %3
Del %1
2.在TortoiseSVN的Setting中选择合并工具(Merge Tool)页面,设置使用外部合并工具(External),在命令行中设置外部合并工具的命令行如下:
"D:\Applications\DevTools\TortoiseSVN\TSVNMerge.bat"
%mine %theirs %merged %base
3.在使用TortoiseSVN编辑冲突文件时,系统会自动打开冲突文件的Mine版本和Theirs版本进行比较合并,用户将所有的修改合并到Mine版本中,当手工编辑冲突完成后,将自动用合并后的Mine版本替代Merged版本,并删除其他文件;这时使用TortoiseSVN的“标识为已解决”,即可进行提交。
此方法可以使用任何支持双向文件比较/合并的工具。
解决方案存在的问题:
这不是一个完美的解决方案,由于使用的是功能有限的批处理文件,因此存在以下问题:
1.无法判断用户是否进行了合并操作,如果没有进行合并操作,也会进行后面的删除和复制操作;
2.有时候会发生复制时提示Merged文件无法修改的情况,这可能是由于比较工具尚未完全退出造成的;
上面的问题可以通过自己编写程序解决,第一个问题通过用文件监视器监视Mine文件来判断是否进行了修改;第二个文件可以通过监视比较工具的进程进行判断。 |