将 SVN Repositories 内部的下层目录,提升成为顶层 Repositories 的风险

         如何将SVN仓库中的一个下层目录提升成到顶层,成为顶层的 Repositories? 我的结论是“无通解”,也就是没有一个通用的方法,并且这种操作是有很大的风险的!

实验一个实例验证一下:

将  Repositories6 中 SVN:Repositories6/Rep6_Folder1 目录,提升一级成为一个顶层的 SVN: Rep6_New

用一般在网络上传播的方法,经过测试,大致的步骤是这样的:

先用 svnadmin dump 命令导出文件;然后过滤修改数据,也就是用 Svndumpfilter 命令过滤出需要的数据;再用编辑器直接编辑修改导出的文件!

编辑器直接编辑修改导出的文件这一步是有很大的风险的,除非数据库中数据,只有最简单的相互依赖关系。

网络上一般给出的编辑修改svnadmin dump 命令导出文件的方法是,将文件中的下面一段文字删除掉,如下:

 

Node-path: 这里填写将要去掉的目录名

Node-kind: dir

Node-action: add

Prop-content-length: 10

Content-length: 10

 

将文件中所有的:

Node-path: 这里填写将要去掉的目录名/

替换成

Node-path: 

 将文件中所有的

Node-copyfrom-path: 这里填写将要去掉的目录名/

替换

Node-copyfrom-path: 

备注:如果导出的文件非常大,Windows下编辑超大文件工具,UltraEdit可能都不好用了,可以借用 Linux(Cygwin) 的 sed 或 ed等编辑工具编辑文件。

如上编辑之后,将编辑修改过的文件,再倒入到一个新建的Repositories库中 (用命令 svnadmin load),则操作完成了旧的底层目录成为了库顶层。以上就是网传的方法。

然而,在实际使用中 Repositories 库中数据可能有着更复杂的相互依赖关系,例如:

希望要提升的目录(也包括文件)可能曾经被修改过名字,甚至删除掉,又重建,你需要仔细查看log,才能知道来龙去脉,上面说的操作方法,不一定就那么简单,一蹴而就,一旦搞错逻辑关系,就会混乱不堪。

最可靠的方法,就是损失掉以往的版本信息,导出export干净的Head版本的数据,添加、并提交到(顶层)新库中。原来已经存在的下层目录,还是放在那里好了,不要动它了。

 

 

一个例子,演示复杂逻辑关系:

停止 SVN 服务

 希望实现:

 Repositories6/Rep6_Folder1 目录提升一级成为一个顶层的Repositories ,先 New_Rep6(新创建的一个空的 Repositories),如图:

导出 Repositories

svnadmin dump Repositories6 > DumpRep6

过滤导出文件,要求仅仅包含有  Rep6_Folder1 目录

Svndumpfilter include Rep6_Folder1 < DumpRep6 > DumpFold1

但是,这会发现问题,导出的文件中,并没有有用的数据:

E:\Repositories>Svndumpfilter include Rep6_Folder1 < DumpRep6 > DumpFold1
Including prefixes:
'/Rep6_Folder1'

Revision 0 committed as 0.
……
Revision 11 committed as 11.
Revision 12 committed as 12.
svndumpfilter: E200003: Invalid copy source path '/folder1'

原因是这里的 Rep6_Folder1 是由 folder1 改名而来的(删除&重建)。看日志:

svndumpfilter 命令中使用包含 include 方式是不行的,因为 Rep6_Folder1 原本的名字是 floder1。这是版本控制的是根,如果被过滤掉了,Rep6_Folder1就没有根了。改用排除法 用命令的参数 exclude ,过滤导出文件就可以了吗?:

Svndumpfilter exclude Rep6_Folder2 < DumpRep6  > DumpFold1

Svndumpfilter exclude Rep6_Folder2 < DumpRep6 > DumpFold1
E:\Repositories>Svndumpfilter exclude Rep6_Folder2 < DumpRep6 > DumpFold1
Excluding prefixes:
'/Rep6_Folder2'

Revision 0 committed as 0.
……
Revision 23 committed as 23.

Dropped 7 nodes:
'/Rep6_Folder2'
'/Rep6_Folder2/0sizeFile.txt'
'/Rep6_Folder2/R6F2'
'/Rep6_Folder2/R6F2F1.txt'
'/Rep6_Folder2/R6F2F2.txt'
'/Rep6_Folder2/Rep6_Folder1'

似乎是OK了,但是还是有陷阱,如果同一级别的目录还有其它的目录,使用中又被删除掉了,也会一并的导入出来了。(示例中的确如此,见下文。需要仔细查看日志,发现这类问题,可以对过滤出的文件,再次的反复的过滤几次。)

下一步编辑 DumpFold1 文件 。 将遇到一些棘手的问题。还是需要仔细查看日志。

然后导入到新建的 Repositories 中:

Svnadmin  load NEW_Rep6 < DumpFold1

导入编辑过后的文件,不一定会成功,导入可能时会遇到一些问题,需要反复几次的编辑修改文件。

例如,可能遇到如下问题:

E:\Repositories>Svnadmin load NEW_Rep6 < DumpFold1
<<< Started new transaction, based on original revision 2
* editing path : Text_BigEndian.txt ...svnadmin: E200014: Checksum mismatch for '/Text_BigEndian.txt':
expected: 9c74ac67638e44e4c8073f608b0655a7
actual: 513155e38d1b941b086234ec289ed6da

这时,你还需要去修改编辑导出的文件,将revision2 的 Text-content-md5:后缀的数字, 修改成上面报告出来的 actual 值。

导入后的截图如下:

 

可以发现, 明显有一个问题 :多出了一个 Rep4_Folder目录。这是一个曾经被添加的目录,然后又删除掉了(有意预留的“炸弹”)。这是编辑修改文件不完善造成了遗留。需要仔细看日志,搞清楚数据之间的逻辑关系,也可以将编辑修改过的文件或过滤掉不需要的文件,用 Svndumpfilter 再次过滤一次或多次。

 

实际导致上面效果,编辑导出的文件方法附如下:(细节部分,忽略)

替换掉folder1/

替换掉Rep6_Folder1/

删除下面一段:

Revision-number: 1
Prop-content-length: 137
Content-length: 137

K 10
svn:author
V 16
VisualSVN Server
K 8
svn:date
V 27
2018-05-25T02:04:35.731309Z
K 7
svn:log
V 25
Created folder 'folder1'.
PROPS-END

Node-path: folder1
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10

PROPS-END

 

删除下面一段

Node-path: Rep6_Folder1
Node-kind: dir
Node-action: add
Node-copyfrom-rev: 12
Node-copyfrom-path: folder1
Content-length: 0

 

Node-path: folder1
Node-action: delete
Content-length: 0

 

Revision-number: 14
Prop-content-length: 112
Content-length: 112

K 8
svn:date
V 27
2018-06-25T02:37:34.462649Z
K 7
svn:log
V 38
This is an empty revision for padding.
PROPS-END

 

然后按照导入失败的提示修改 Text-content-md5 后面的数字。前文已描述过了。

posted on 2018-06-25 17:21  johnphan  阅读(756)  评论(8编辑  收藏  举报

导航