将Subversion存储库项目拆分为两个Git存储库

时间:2012-07-06 18:30:10

标签: git svn version-control git-svn

我有一个Subversion服务器,在标准布局中有几个不同的项目,如下所示:

ProjectA/
    trunk/
    branches/
    tags/
ProjectB/
    trunk/
        FolderOfBinaries/
        SourceFolderA/
        SourceFolderB/
        SourceFolderC/
    branches/
    tags/
        v1.0/
        v1.1/
        v2.0/
ProjectC/
    trunk/
    branches/
    tags/

ProjectB将被迁移到Git,但不会迁移到标准克隆。我想将项目拆分为两个Git存储库 - 一个用于充满大量二进制文件夹的文件夹,这些二进制文件经常更改,另一个用于其他所有存储库。我完全克隆了存储库并且它只有几GB,但是二进制文件夹大概是其中的90%,并且运行git gc需要很长时间。我宁愿拥有一个小型快速存储库,然后在开发人员需要时将二进制文件夹添加为子模块。

到目前为止,我找到了两个可能的选择。首先,我可以使用git branch-filter尝试从Git Book中显示的历史记录中删除二进制文件夹。其次,我可以使用svndumpfilter将当前的Subversion存储库拆分为两个,然后分别为git svn clone

我的问题是,所有的历史,特别是分支和标签会发生什么?我仍然想知道项目中每个标记的二进制文件夹是什么样的,即使两个标记之间的二进制文件可能没有变化。那可能吗?

编辑:二进制文件夹中没有构建文件(* .class,* .o,* .dll等),因此我不能将其删除并使其外部。它充满了从需要进行版本化的第三方程序输出的二进制文件(想想OpenOffice文档,Photoshop文件等)。

3 个答案:

答案 0 :(得分:1)

我建议svndumpfilter首先将ProjectB拆分为两个存储库。之后,您可以使用git svn clone将新的SVN存储库转换为GIT存储库。 当--include svndumpfilter模式考虑trunk,branches和tags文件夹时,将保留拆分存储库的完整历史记录。因此,您可以查看新二进制存储库中FolderOfBinaries的所有历史记录。

使用git svn clone创建GIT存储库时,branches文件夹的内容将转换为GIT分支,tags文件夹的内容将转换为GIT标记。

答案 1 :(得分:1)

看看svndumpfilter。它使用起来非常简单。您执行Subversion存储库转储,然后使用过滤器来说出您想要的内容或您不想要的内容。

转储当前存储库,然后运行svndumpfilter两次 - 每个Git存储库一次。你可以链接它们。只需为每个Git存储库运行两次。

$ svndumpfilter include ProjectB < svn_repo_dump | svndumpfilter exclude ProjectB/trunk/folderofbinaries > svn_repos_no_binaries

我想提一件事:不要在您的存储库中存储构建的二进制对象。在Subversion中,如果没有转储和过滤器,它们就无法移除,即使在能够删除修订版本的版本控制系统中,这样做也需要花费大量的时间和精力。这是一个很大的维护问题。

为了什么?在版本控制系统中存储二进制文件并没有多大帮助。您不能 diff 二进制文件,历史记录没有帮助,非开发人员很难访问它们。

相反,请使用发布存储库,并将二进制文件存储在那里。即使您不使用Maven甚至使用Java,也可以使用Artifactory或Nexus等Maven存储库。

答案 2 :(得分:1)

好吧,我已经设法做到了这一点,但并不是那么简单。可能有更好的方法,但不是我可以解决的问题。我做了以下事情:

  1. 创建当前存储库的转储:svnadmin dump /opt/repo > full_dump

  2. 过滤转储以删除二进制文件夹:svndumpfilter exclude *folderofbinaries* --pattern --renumber-revs --drop-empty-revs < full_dump > filtered_dump。我需要使folderofbinaries成为一种模式,因为过去有人实际上已经将二进制文件直接检入标记(!),因此下一步因缺少文件夹而失败。

  3. 使用筛选转储创建本地SVN存储库: mkdir repo-filtered; svnadmin create repo-filtered; svnadmin load repo-filtered < filtered_dump

  4. 将完整和已过滤的repo克隆到不同的文件夹中(我使用svn2git)。过滤后的仓库不包含任何二进制文件。如果在完整仓库中,只有二进制文件夹在标签A和B之间发生了变化,那么在新过滤的Git仓库中,两个标签将指向同一个提交,这正是我想要的。

  5. 在完整的Git仓库中,使用Git删除除二进制文件夹以外的所有内容。

  6. 我必须使用Git来隔离二进制文件夹的原因是因为我无法解决如何使用svndumpfilter来维护标记(特别是考虑到我将二进制文件直接提交到标记中)。转换后,我得到与过滤后的repo相同的行为 - 如果两个标签之间没有更改二进制文件,那么它们都指向同一个提交。

    最后一步的命令是:

    git checkout master
    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter folderofbinaries -- --all
    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --prune=now
    

    我是从this question获得的。

    现在我有一个80MB的源存储库和一个1.5GB的二进制存储库,来自我原来的4.4GB SVN转储文件!我可以通过添加二进制文件夹作为源repo的Git子模块并在每个上检查相同的标签来重新创建原始SVN repo的确切状态(这就是为什么我需要保留所有标签信息)而没有一个猛犸象使用缓慢的Git回购。