【问题标题】:How to split an SVN folder into its own repository when it has been renamed?SVN文件夹重命名后如何将其拆分为自己的存储库?
【发布时间】:2010-09-30 19:15:15
【问题描述】:

我想将一个目录从一个大型 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 解决方案可以做到这一点,遗憾的是它不可行,因为路径/文件已经移动了。 solution by ng 是不可接受的,因为它基本上是克隆+删除额外内容,保留所有历史记录,而不仅仅是相关的 myproj 历史记录。

【问题讨论】:

  • 你能解决这个问题吗?
  • 实际上没有,尽管我需要尝试 auriarte 建议的第 3 方脚本。该项目现在已经冻结了一段时间,因此我也一直在忽略这个问题,但我会尝试一下。
  • 我在 svn 1.5 的 17G 存储库中遇到了同样的问题。我必须排除 15 条不同的路径,并且从我们拥有的 12000 修订号 1259 上中断。呵呵!!!

标签: svn repository split


【解决方案1】:

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

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 与回购的其余部分分开。 另一方面,当排除 D 时我没有收到错误,我猜是因为删除 D 不需要 A、B、C 的链接/历史记录

【讨论】:

  • 这也解决了我的问题,希望其他人能看到。我们遇到了一个问题,我们的主工作文件夹从“Abc_Fun”重命名为“AbcFun”再到“Fun[Abc]”等等,所以包括额外的路径不是问题。
  • 赞成,因为也解决了我的问题。希望它至少成为第二选择的帖子
  • @non-existent atws account: 抱歉,这个账号已经不存在了,所以普通模组不能合并账号。有人必须先取消删除/恢复帐户。我不确定在这种情况下是否可行。请在 meta 上寻求帮助。
【解决方案2】:

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

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

【讨论】:

  • 该脚本让我克服了创建新转储文件时所描述的问题,但是当我尝试将转储加载到新存储库时,我发现了一个不同的问题。
  • 您的链接有 404'd。您可以将脚本添加到您的答案中吗?
  • 我在使用 svndumpfilter3 时遇到了(与 python 相关的?)问题,但使用 svndumpfilter2 成功过滤了 13.000 版本的存储库,转储大小为 1.5G
  • 谢谢。该脚本在稍作修改后即可工作。出于某种原因,它试图在解开时将“srcpath”参数传递给“svnadmin dump”。这使得 svnadmin 失败。我不得不从命令中删除该参数,它起作用了。
【解决方案3】:

我已经尝试了至少 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

这是我尝试过但没有奏效

【讨论】:

  • 我非常感谢您创建了这个工具,我最终得到了它的工作,但有些事情与您所说的不同。 1) 为了让svnlook 工作,我实际上需要为--repo 提供一个实际未压缩存储库的路径,而不是您的示例所示的.dump 文件。我收到myrepo.dump/format 不存在的错误。我必须对 .dump 文件执行 svnadmin load 并将 --repo 指向它。 2) 在--scan-only 模式下,--output-dump 选项仍然是必需的,否则会报错。
【解决方案4】:

这可能会帮助您: 引用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 不再有效时停止镜像数据。

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

【讨论】:

    【解决方案5】:

    auriarte 到 svndumpfilter3 404 的链接。这是一个工作链接(截至 2011 年 1 月 31 日),任何人都在寻找它:http://furius.ca/pubcode/pub/conf/bin/svndumpfilter3.html

    【讨论】:

      【解决方案6】:

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

      这终于对我有用了...

      1. 使用 svnsync 按照here 的指示制作我的 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'
      

      但是 Charles Calvert 博客中的 post 解释说,所需要的只是在执行加载之前在 foorepo 中创建主干目录。

      【讨论】:

        【解决方案7】:

        我遇到了这个问题,最终使用了 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 的复制存储库中执行此操作。

        【讨论】:

          【解决方案8】:

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

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

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

          【讨论】:

          • 我似乎无法让它工作,你能添加更多具体的命令来做到这一点。它只是跳过不存在的文件,所以我可能做错了。顺便说一句,这与复制 repo 并删除除我的目录之外的所有其他内容有何不同?我也想摆脱不相关的历史等?
          • 只删除你不想要的没有区别。但是,如果您希望新的存储库 /trunk 成为旧的存储库 /trunk/whatever ,那么您需要将转储的完整 /trunk 复制到 /branches 只复制您想要的 /trunk ,我会添加另一个答案细节。
          • 问题是新仓库的备份会比原来的更大(如果你这样做的话)。
          【解决方案9】:

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

          好的:

          Subversion 的重写 svndumpfilter 在纯 Python 中,即 允许您解开移动/复制 排除和之间的操作 包括文件/目录集,由 将它们转换为加法。如果你 使用此选项,它会获取 给定的原始文件 存储库。

          关注:

          重要

          有些人一直在报告错误 使用此脚本,它将创建 大型存储库上的空文件。 它对我的分裂很有效 必须在我的存储库上做,但我有 没有时间解决发生的问题 对于其他人的存储库

          【讨论】:

            【解决方案10】:

            偶然发现了这个问题,发现了这个工具svndumpsanitizer它似乎工作得很好,我能够将它创建的文件导入到一个新的存储库中。

            【讨论】:

            • 仅作记录,如果您想在 Win32 上构建它,请添加 #include 并将 fseeko 替换为 fseek。也编译为 c++ 而不是 c(在 C/C++/Advanced/Compile As 下设置的 vs8 中)
            • svndumpsanitizer 让我成功拆分了 svndumpfilter 和 svndumpfilter3 都无法处理的大型 SVN 1.7 存储库。
            【解决方案11】:

            这是在过于复杂的黑暗中进行的疯狂而疯狂的尝试,但是使用 git-svn/[tailor][3] 将 SVN 存储库导入 git,使用 git-split 拆分目录,然后导出呢?用git-svn返回svn?

            【讨论】:

              【解决方案12】:

              具体命令如下,我将假设存储库托管在 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
              

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

              【讨论】:

              • 这仍然是“保留一切的历史”解决方案。我需要一个复制 svndumpfilter 解决方案精神的解决方案:/
              【解决方案13】:

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

              【讨论】:

              • 抱歉,没有。我想出了空转储或像以前一样出现“无效的复制源路径”错误:(
              【解决方案14】:

              如果您不需要整个历史记录,您可以在错误发生后立即获取它。如果您的错误是在修订版 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
              

              【讨论】:

                【解决方案15】:

                关于 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 脚本)。

                【讨论】:

                • 那个新脚本真的帮助了我,转储是应该的......没有错误,没有警告。 SVNADMIN LAOD 也很好。我们的程序员告诉新的 repo 应该是这样的。所以 5*
                • 帮助.. 是的,从转储中转储文件夹没有错误,甚至将其加载到空仓库中。但请注意:您使用这种转储的新存储库是不行的。在使用构建服务器(例如,Hudson 或 Cruise Cntrol)时,您的一些数据会丢失并且可能是一个巨大的问题。您可能会有: 无法访问修订时间。 [500, #0] [客户端 10.0.0.71] 或无法传送内容。 [409, #0] [client 10.0.0.229] 所以请三思而后行,在投入生产之前进行测试。
                【解决方案16】:

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

                #!/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
                

                【讨论】:

                • 只是评论,转储成功,但是重新导入没有成功。所以,那里没有运气。 (上周用 git svn clone 切换到 git)
                【解决方案17】:

                基于 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"
                

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

                【讨论】:

                  【解决方案18】:

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

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

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

                  小型存储库可以免费细分。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-03-13
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-03-04
                    • 2020-01-30
                    相关资源
                    最近更新 更多