42

我想将一个大型 Subversion 存储库中的目录拆分为它自己的存储库,并保留该目录中文件的历史记录。

我先尝试了常规的方法

svnadmin dump /path/to/repo > largerepo.dump
cat largerepo.dump | svndumpfilter include my/directory >mydir.dump

但这不起作用,因为多年来该目录已被移动和复制,并且文件已被移入和移出到存储库的其他部分。结果是很多这样的:

svndumpfilter: Invalid copy source path '/some/old/path'

接下来我尝试将/some/old/path它们包含在内,并且在包含一长串文件和目录之后,svndumpfilter 完成,但是导入结果转储不会产生与当前目录相同的文件。

那么,如何在保留历史记录的同时正确地从该存储库中拆分目录?

编辑:我特别想trunk/myproj成为新存储库中的主干加上新存储库不包含其他旧东西,即。任何人都不应该在拆分之前更新到旧版本并获取/查看文件。

我尝试的 svndumpfilter 解决方案可以实现这一点,遗憾的是它不可行,因为路径/文件已被移动。ng的解决方案是不可接受的,因为它基本上是一个克隆+删除额外的东西,它保留了所有的历史,而不仅仅是相关的 myproj 历史。

4

16 回答 16

17

我在拆分存储库时遇到了类似的问题..

svndumpfilter: Invalid copy source path /dir/old_dir

我为解决这个问题所做的就是包含正在请求的其他旧目录,或者您知道您已移动。就我而言,我已将 3 个目录移动到另一个目录中。

例如。将文件夹 A、B、C 移入文件夹 D

cat project.dump | svndumpfilter include A B C D > new.dump

这似乎解决了我的问题。我能够将文件夹 D 与回购的其余部分分开。另一方面,当排除 DI 没有得到错误时,我猜是因为删除 D 不需要 A、B、C 的链接/历史记录

于 2009-05-22T01:47:21.937 回答
14

当 svndumpfilter 最初包含的目录/文件之一被复制或从未包含的树的一部分中移动时,会出现此问题。

要解决此问题,请使用此脚本:svndumpfilter3

于 2009-07-23T08:32:51.317 回答
6

我已经尝试了至少 4 种不同的应用程序来做到这一点,唯一真正有效的是使用 svndumpfilterIN

cd /usr/local/bin/
sudo wget --no-check-certificate https://raw.github.com/jasperlee108/svndumpfilterIN/master/svndumpfilter.py
sudo chmod +x svndumpfilter.py
# To be sure nothing will happened on the original repo :
cp -au /path/to/repo /tmp/largerepo.repo/
svnadmin dump /path/to/repo > /tmp/largerepo.dump
svndumpfilter.py /tmp/largerepo.dump --repo=/tmp/largerepo.repo --output-dump=/tmp/mydir.dump include my/directory

这是我尝试过但没有奏效的方法:

于 2014-03-05T10:08:55.737 回答
3

这可能会对您有所帮助:引用http://svnbook.red-bean.com/en/1.5/svn.reposadmin.maint.html#svn.reposadmin.maint.replication

在 Subversion 1.5 中,svnsync 增加了镜像存储库子集而不是整个事物的能力。设置和维护这样一个镜像的过程与镜像整个存储库时完全相同,除了在运行 svnsync init 时不指定源存储库的根 URL,而是指定该存储库中某个子目录的 URL。与该镜像的同步现在将仅复制该源存储库子目录下更改的位。但是,这种支持有一些限制。首先,您不能将源存储库的多个不相交的子目录镜像到单个镜像存储库中——您需要镜像一些两者共有的父目录。二、过滤逻辑完全基于路径,因此,如果您要镜像的子目录在过去的某个时间点被重命名,则您的镜像将仅包含自该目录出现在您指定的 URL 以来的修订。同样,如果将来重命名源子目录,您的同步过程将在您指定的源 URL 不再有效时停止镜像数据。

问题当然是丢失了重命名历史......

于 2009-01-21T16:46:23.987 回答
3

我遇到了这个问题并最终使用了 svndumpfilter2。

具体来说,这个命令:

sudo svnadmin dump /home/setup/svn/repos/main_repl | sudo ./svndumpfilter2.py /home/setup/svn/repos/main_repl Development QA compliance > ~/main_repl_dump.trim

我确实收到了提到的内存不足错误,但是,由于我在 VM 上运行 svn,我只是将内存提高到 2G。虽然我意识到这可能不是每个人的选择,但我注意到它的运行速度比 512M 快得多(2G 可能不是必需的)。

目前,它正在处理修订版 18,631。

万一有人想知道,我需要拆分部分 repo 的原因是因为我们正在创建标签/副本以分发到 repo 的另一个路径中的文件实现。出于某种原因,这个过程导致回购膨胀到巨大的比例。(我们现在是 17G。)

我在 Debian Lenny 5.0.4 的 SVN 版本 1.5.6 的复制存储库中执行此操作。

于 2010-03-30T19:50:01.447 回答
3

我刚刚成功地将一个项目从现有的组合存储库(在 Google 代码)迁移到它自己的存储库。这里的帖子很有帮助。

这终于对我有用了......

  1. 使用 svnsync 按照此处的说明制作我的 Google 代码仓库的本地镜像。
  2. svnadmin dump to foo-dumpfile
  3. cat dumpfile | ./svndumpfilter3 --untangle mymirrorrepo trunk/foo > foo-dumpfile
  4. svnadmin create foorepo
  5. svnadmin load foorepo --ignore-uuid < foo-dumpfile

第 3 步中的--untangle选项设法解决了所有困扰 svndumpfilter 和 svndumpfilter2 的路径问题。

最初,在第 5 步,我遇到了错误:

<<< Started new transaction, based on original revision 2
svnadmin: File not found: transaction '1-1', path 'trunk/foo'

但是查尔斯卡尔弗特博客中的这篇文章解释说,所需要的只是在执行加载之前在 foorepo 中创建主干目录。

于 2011-03-22T00:35:45.867 回答
2

为什么不复制整个存储库,将其转储到新存储库。然后分支出主干,删除头部并将您想要的部分从分支合并回主干。然后你保留了历史并将你想要的部分拆分到一个新的存储库中。

  1. 转储到 /trunk
  2. 分支 /trunk 到 /branches/trunk
  3. 删除/主干
  4. 合并 /branches/trunk/whatever 到 /trunk 或 /trunk/whatever

这样,您就保留了所有历史记录,并有选择地选择了您想要的部分。

于 2009-01-11T17:53:34.740 回答
2

我也在寻找这个问题的答案(必须自己处理)。根据 Alex 的回答,我发现 http://furius.ca/pubcode/pub/conf/common/bin/svndumpfilter3.html 声称可以修复一些 svndumpfilter2 问题。我相信这是一个部分的解决方案。

好的:

用纯 Python 重写了 Subversion 的 svndumpfilter,它允许您通过将排除和包含的文件/目录集转换为附加集来解开移动/复制操作。如果您使用此选项,它将从给定存储库中获取原始文件。

忧虑:

重要的

有些人一直在报告这个脚本的一个错误,它会在一个大型存储库上创建一个空文件。它非常适合我必须在我的存储库上进行的拆分,但我没有时间解决其他人的存储库出现的问题

于 2010-03-22T13:41:13.307 回答
2

这是在过于复杂的黑暗中疯狂而疯狂的刺伤,但是如何使用git-svn /[tailor][3]将 SVN 存储库导入 git ,使用git-split 拆分目录,然后将其导出回svn 与git-svn

于 2010-03-22T13:48:36.590 回答
1

具体命令如下,我将假设存储库托管在 http(s):// 服务器上,尽管相同的命令适用于 svn:// 或 file://。

svnadmin dump /path/to/repository > dumpfile  
svnadmin create /path/to/new_repository 
svnadmin load /path/to/new_repository < dumpfile 
svn co https://localhost/svn/new_repository_url new_repository_checkout 
cd new_repository_checkout 
svn move https://localhost/svn/new_repository_url/trunk  https://localhost/svn/new_repository_url/branches/head -m "Moving HEAD to branches" 
svn move https://localhost/svn/new_repository_url/branches/head/whatever https://localhost/svn/new_repository_url/trunk -m "Creating new trunk" 
svn update 
cd branches 
svn remove head
svn commit

您现在应该将旧存储库中所需的部分作为新存储库的主干。

于 2009-01-11T19:56:02.527 回答
0

我看到这已经很老了,但是添加“--skip-missing-merge-sources”有帮助吗?好像可能...

于 2009-04-27T21:02:18.897 回答
0

如果您不需要整个历史记录,您可以在错误发生后立即获取它。如果您的错误出现在修订版 412 中,那么您可以尝试在之后立即将其捡起:

svnadmin dump /path/to/repo -r 413:HEAD > largerepo.dump

我意识到这可能也不是一个完美的解决方案,但在你的情况下它可能已经足够好了。

您可能还想一步完成这一切

svnadmin dump /path/to/repo -r 413:HEAD | svndumpfilter include my/directory > mydir.dump
于 2009-05-06T21:32:48.747 回答
0

有关 svndumpfilter 以及如何修复的更多信息 - http://blog.rlucas.net/uncategorized/some-gotchas-with-using-svndumpfilter/

或者您可以尝试 svndumpfilter 替换脚本,现在称为 svndumpfilter2 - http://cogo.wordpress.com/2009/03/10/problems-with-svndumpfilter/

我没有尝试过那个脚本,因为我需要一些时间来做一个 repo 备份,来测试它(我有一个备份转储可以玩,但在 Windows 上,它是一个 linux 脚本)。

于 2010-01-21T15:01:47.290 回答
0

刚刚遇到这个问题并编写了一个小脚本来重试转储,直到解决所有无效的源路径。

#!/usr/bin/env ruby

require 'open3'
include Open3

paths = [ "/your/path" ]
command = ""

new_path = "xx"
while (! new_path.nil?)
lines = nil
popen3(" svndumpfilter include #{paths.join(' ')} > svn.result.dump < svn.original.dump") do |i, o, err|
  i.close
  puts "Processing, please wait ..."
  lines = err.readlines
end

 new_path = nil
 lines.each do |line|
  if line =~ /Invalid copy source path '(.*)'/
    new_path = $1
  end
 end
 puts "Adding #{new_path}"
 paths << new_path
end
于 2010-05-07T23:14:04.653 回答
0

基于 ng. 的回答,但过滤和删除空修订。

步骤 1.转储和过滤:

svnadmin dump /path/to/repository > fulldumpfile
svndumpfilter include trunk/the/part/you/want --drop-empty-revs --renumber-revs < fulldumpfile > dumpfile

步骤 2.创建新的仓库。(请注意,这也可以使用 Tortoise SVN 来完成)

svnadmin create /path/to/new_repo

请记住添加您需要能够结帐的任何内容(权限等)。

第 3 步。结帐并添加基本文件夹(也可以使用 Tortoise SVN 完成)

svn checkout http://localhost/new_repo /some/checkout/path/newrepo
cd /some/checkout/path/newrepo
# to be able to create "trunk/the/part/you/want" you will need to add parent dir:
mkdir -p trunk/the/part/you
svn add trunk
svn commit -m "old base"

步骤 4.加载过滤后的转储

svnadmin load /path/to/new_repo < dumpfile

步骤 5.将旧根移动到新根(也可以使用 Tortoise SVN)

cd /some/checkout/path/newrepo
svn update
svn move trunk/the/part/you/want/* trunk/
svn move tags/the/part/you/want/* tags/
svn move branches/the/part/you/want/* branches/
svn commit -m "re-structure base"

您现在应该将旧存储库中所需的部分作为新存储库的主干。

于 2014-05-09T14:31:52.167 回答
0

我们开发了Subdivision,一个用于拆分 svn 存储库的 GUI 工具。

细分分析存储库并计算文件在整个存储库中被复制和移动时的历史记录。使用此信息,您的选择会得到智能扩充,以避免所有“无效的复制源路径”错误。

除了拆分存储库之外,Subdivision 还可用于从存储库中删除文件以及将文件和文件夹提取到新存储库中。

对于小型存储库,细分是免费的。

于 2016-02-03T22:07:45.510 回答