4

我有一个 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 文件等)。

4

3 回答 3

1

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

转储当前存储库,然后运行 ​​svndumpfilter 两次——每个 Git 存储库运行一次。你可以把它们串起来。只需为每个 Git 存储库运行两次。

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

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

为了什么?在版本控制系统中存储二进制文件并没有真正的帮助。您无法区分二进制文件,历史记录无济于事,而且非开发人员很难访问它们。

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

于 2012-07-08T21:55:05.200 回答
1

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

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

于 2012-07-08T17:41:20.927 回答
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)。过滤后的 repo 将不包含任何二进制文件。如果在完整的仓库中,只有二进制文件夹在标签 A 和 B 之间发生了变化,那么在新过滤的 Git 仓库中,这两个标签将指向同一个提交,这正是我想要的。

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

我必须使用 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

我从这个问题中得到的。

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

于 2012-07-11T20:26:54.877 回答