将多个SVN存储库合并为一个

时间:2008-11-06 00:18:57

标签: svn

在考虑了我之前的问题(One SVN Repository or many?)的答案之后,我决定采用我拥有的4个左右的存储库并将它们合并为一个。这当然会导致一个问题,最好的方法是什么?

有没有办法组合两个或多个存储库来维护两者的版本历史记录?

编辑:我还应该指出我正在使用Assembla.com,它不提供对svnadmin命令的访问权限,AFAIK

另一个编辑:这是否重要?如果svnadmin适用于URL,那么就没问题了。

6 个答案:

答案 0 :(得分:72)

编辑:哦,问题编辑是在我打字时进行的。这是

的答案
  

有没有办法合并两个或更多   存储库维护版本   两者的历史?


假设

现有存储库的结构如下:

  • 存储库根目录
    • 分支
    • 标记
    • 躯干

你需要一个类似的结构:

  • 存储库根目录
    • 了projectA
      • 分支
      • 标记
      • 躯干
    • 项目B
      • 分支
      • 标记
      • 躯干

然后为每个项目存储库:

svnadmin dump > project<n>.dmp

然后为每个转储文件:

svn mkdir "<repo url>/project<n>"
svnadmin load --parent-dir "project<n>" <filesystem path to repos>

更复杂的操作是可能的,但这是最简单,最直接的。在转储/加载期间更改源存储库结构是危险的,但可以通过svnadmin dumpsvndumpfilter,手动编辑或其他文本过滤器和svnadmin load

的组合来实现

与第三方提供商打交道

  • 为每个存储库请求svnadmin dump个文件。提供商应该愿意/能够提供这个 - 您的代码!
  • 在本地创建SVN存储库。
  • 执行上面列出的转储文件操作。
  • 使用您最喜欢的客户端验证存储库结构是否正确。
  • 为组合存储库创建转储文件。
  • 请求提供程序从此转储文件填充新存储库。

YMMV:这似乎是一种合理的方法,但我从未与这样的第三方提供商合作过。

答案 1 :(得分:10)

使用Subversion 1.7,您现在可以远程执行转储。也就是说,无需访问本地文件系统和svnadmin dump命令。

您可以使用svnrdump来获取远程存储库的完整转储。有关语法详细信息,请参阅文档。

请注意,服务器不必运行1.7,只需运行客户端。

http://svnbook.red-bean.com/en/1.7/svn.ref.svnrdump.c.dump.html

答案 2 :(得分:9)

是的,使用svnadmin dumpsvnadmin load

我们假设您需要存储库,一个使用HEAD修订版100,另一个使用HEAD修订版150.

您转储第一个存储库并将其加载到新存储库中:最终得到第一个存储库的完整故事,从修订版0到修订版150.

然后您转储第二个存储库并将其加载到新存储库中:它将加载其完整历史记录,唯一改变的是实际修订版本号。第二个存储库的历史记录将在新版本的存储库中表示,从版本151到版本250。

两个存储库的完整历史记录都是保存程序,只有导入第二个存储库的修订号才会更改。

同样适用于两个以上的存储库。

编辑:我在编辑时发布了,所以我没有看到你的笔记......

答案 3 :(得分:3)

如果您无法访问svnadmin,那将很难但是可行。假设您有存储库A和B,并希望将它们合并到存储库C中。以下是您必须使用的步骤来实现此目的。

  1. 将存储库A的修订版1签出到您的硬盘。

  2. 在C存储库的根目录下创建一个名为Repository_A的目录,并将其签出到本地硬盘。

  3. 将您的A(减去).svn文件中的文件复制到Repository_A文件夹中的C结帐中。

  4. 在C上执行提交。

  5. 将您的存储库A的工作副本更新为版本2,并执行步骤3和4,并重复每个连续的修订,直到您到达头部。

    现在对B.做同样的事情。

    这基本上和@Davide Gualano建议的一样,不需要svnadmin。您可以编写一个简单的脚本来为您执行此操作,如果没有很多修订,您可以手动执行此操作。

答案 4 :(得分:3)

您可以使用以下步骤在一个存储库中加载许多转储文件。

存储库根目录:

 projectA
    branches 
    tags
    trunk
 projectB
    branches
    tags
    trunk

首先,您必须在存储库根目录中创建目录(项目A,项目B),如下所示:

$ svn mkdir -m "Initial project root" \
file:///var/svn/repository_root/Project_A\
file:///var/svn/repository_root/Project_B\
file:///var/svn/repository_root/Project_C\

Revision 1 committed.

之后您可以加载转储文件:

使用参数--parent-dir DIRECTORY

$ svnadmin load /var/svn/repository_root --parent-dir Project_A < file-dump-PRJA.dump
…
$ svnadmin load /var/svn/repository_root --parent-dir Project_B < file-dump-PRJB.dump

这样,您将拥有一个包含许多转储存储库的存储库。

答案 5 :(得分:1)

这个问题的其他答案使我能够制作下面的脚本。根据您的情况调整REPOS地图。此外,您可能希望将标记和分支移动到“预聚合”目录中,而不是直接进入新的分支和主干。

#!/bin/bash

NEWREPO=$(pwd)/newrepo
NEWREPOCO="${NEWREPO}_co"
DUMPS=repodumps
REV="0:HEAD"
REPOROOT=/data/svn/2.2.1/repositories/
TOOLDIR=/opt/svn/2.2.1/bin/
PATH=${PATH}:${TOOLDIR}

# Old Repository mapping 
declare -A REPOS=( 
    [BlaEntityBeans]='(
        [newname]="EntityBeans"
    )'
    [OldServletRepoServlet]='(
        [newname]="SpreadsheetImportServlet"
    )'
    [ExperimentalMappingXML]='(
        [newname]="SpreadsheetMappingXML"
    )'
    [NewImportProcess]='(
        [newname]="SpreadsheetImportProcess"
    )'    
)

dump() {
    rm -fr ${DUMPS}
    mkdir ${DUMPS}
    for repo in "${!REPOS[@]}"
    do
        local dumpfile=${DUMPS}/${repo}.dmp
    echo "Dumpimg Repo ${repo} to ${dumpfile}"
        svnadmin dump -r ${REV} ${REPOROOT}/${repo} > ${dumpfile}
    done
}

loadRepos() {
    # new big repo
    rm -fr ${NEWREPO}
    svnadmin create ${NEWREPO}
    svn mkdir file:///${NEWREPO}/trunk -m ""
    svn mkdir file:///${NEWREPO}/branches -m ""
    svn mkdir file:///${NEWREPO}/tags -m ""

    # add the old projects as modules
    for currentname in "${!REPOS[@]}"
    do  
        declare -A repo=${REPOS[$currentname]}
        local newname=${repo[newname]}
        echo "Loading repo ${currentname} soon to be ${newname}"
        dumpfile=${DUMPS}/${currentname}.dmp

        # import the current repo into a trmporary root position
        svn mkdir file:///${NEWREPO}/${currentname} -m "Made module ${currentname}"
        svnadmin load --parent-dir ${currentname} ${NEWREPO} < ${dumpfile}

        # now move stuff arround
        # first rename to new repo
        svn move file:///${NEWREPO}/${currentname} file:///${NEWREPO}/${newname} -m "Moved ${currentname} to ${newname}"
        # now move trunk, branches and tags
        for vc in {trunk,branches,tags}
        do
            echo "Moving the current content of $vc into ${NEWREPO}/${vc}/${newname}"
            svn move file:///${NEWREPO}/${newname}/${vc} file:///${NEWREPO}/${vc}/${newname} -m "Done by $0"
        done
    svn rm  file:///${NEWREPO}/${newname} -m "Removed old ${newname}"
    done
}

dump
loadRepos