svn - 仅从 git 转换 subversion 存储库的一部分

标签 svn git

我有一个旧的 Subversion 存储库,里面有很多我的私有(private)项目。它的一部分是几年前从一个旧的 CVS 存储库(使用 cvs2svn 或类似的)转换而来的。它当前的结构如下所示:

  • 后备箱
    • latex
    • java
      • awt独库
      • 页数
        • build.xml
        • 来源
          • Ant
            • dclj
            • 常见问题
            • 保罗
              • (大约 20 个其他包)
              • ltxdoclet
                • (一些java文件)
    • 路亚
    • (其他目录)
  • 分支机构
  • 标签
  • 导入
一个问题是我对这个存储库做了相当多的重组 - 例如,pps 目录的所有内容曾经在 import 的子目录中(我想我导入了它来自 CVS),并且可能还有其他 Action 。

我现在对 ltxdoclet 目录的内容以及路径中的一些其他文件感兴趣,例如 build.xml、ant 目录等。我想拥有他们的全部历史记录,包括移动文件之前的任何历史记录。我现在想把它作为一个 git 存储库(因为我想在 github 上发布它)。标签和分支从未真正使用过,所以它们并不重要。

我不想要这个存储库的其余部分(他们有时会得到单独的 git 存储库)——这会把我的存储库炸得太多(有些东西我不想发布)。

理想情况下,我生成的 git 存储库(处于 HEAD 状态)应该如下所示:

  • 页数
    • build.xml
    • 来源
      • Ant
        • dclj
          • 保罗
            • ltxdoclet
              • (一些java文件)
我不太关心历史目录配置,但历史不应包含任何未触及这些目录(或其前身)中的任何文件的提交。


当然,git svn似乎是首选工具。 (还有其他人吗?)

git svn clone 似乎是正确的命令……但有哪些选项?我创建了一个 authors.txt 来将 CVS 或 SVN 用户名转换为我的姓名和地址。为了只包含感兴趣的文件和目录,我使用了 --ignore-paths

这是我的尝试:

filter='^/xcb-src/|_00|src/resources|dclj/faq|dclj/paul/([^l]|l[^t])'
git svn clone svn+ssh://mathe-svn/ --trunk trunk/java/pps -A authors.txt --ignore-paths=$filter latexdoclet

当然,它只显示提交 2306 之后的历史记录,当我将 import/java-pps 移动到 trunk/java/pps 时......它有很多完全没有变化的提交数。

为了解决第一个问题,我考虑过将旧目录也作为--trunk:

git svn clone svn+ssh://mathe-svn/ --trunk trunk/java/pps --trunk import/java-pps -A authors.txt --ignore-paths=$filter latexdoclet

这不起作用,第一个 --trunk 在这里被忽略,它在提交 2305(移动之前)有效结束。 (而且它还包含很多空提交。)

我目前的尝试是导入整个存储库,过滤掉任何不需要的东西:

filter='/xcb-src/|_00|src/resources|dclj/faq|dclj/paul/([^l]|l[^t])|/esperanto|finanzen|diverses|homepage|konfig|lua|prog-aufgaben|CVSROOT|latex|tags/'
git svn clone svn+ssh://mathe-svn/ -A authors.txt --ignore-paths=$filter latexdoclet-neu

转换仍在运行,但肯定有很多我根本不想要的提交。

编辑:转换完成 - 我现在有 2658 次提交(git 中的 3176 个对象),如果我正确配置我的 gitk 过滤器,其中只有大约 36 个有一些有趣的树更改。 (+ 大约 3 个被错误地过滤掉了,因为我们的 latex 源文件首先位于 latex 目录中。)


  • 有没有人对如何做到这一点有更好的想法?
  • 我是不是应该先导入整个存储库,然后再使用 git filter-branch?挑选出我想要的文件和提交?

最佳答案

这里是我做的,供引用。


在 Dustin 的回答后,我首先将整个 svn 存储库转换为 git,用

 git svn clone -A authors.txt svn+ssh://mathe-svn/ all-projects

这让我从一个 45 MB 的 git 存储库中得到了一个相当大的 git 存储库,其中包含 24241 个对象和 24 MB(打包后)。正如已经说过的评论,两者在线性历史中都有 2658 次提交,所以到现在为止什么都没有丢失。

然后我开始从 git filter-branch 提供的过滤器中过滤掉... , --index-filter 似乎是最有用的,因为它不需要检查任何东西(与 --tree-filter 相比),我做到了不想重写元数据,只删除不需要的文件。

此外,--prune-empty 也会很有用。我还使用 -d/dev/shm/ebermann/git-work/tmp 将工作目录放在 tmpfs 中,但我不知道这是否真的很重要,因为我在这里没有检查.我使用 --original 选项以新名称保存原始 master 引用。 (为什么 filter-branch 不允许简单地创建一个新分支而让旧分支保持完整?)

作为我的树过滤器,我使用了 git rm --cached -r --ignore-unmatch,我通过 xargs 向其提供了文件和目录列表.

所以,我有多个

git filter-branch           \
  -d /dev/shm/ebermann/git-work/tmp  \
   --index-filter "
xargs -a ~/projektoj/git-conversion/remove-liste-5.txt git rm --cached -r --ignore-unmatch 
"        \
   --original "step8"       \
   master

git filter-branch \
  -d  /dev/shm/ebermann/git-work/tmp  \
  --prune-empty \
  --original "step9" \
  master

其间,我用gitk查看了创建的分支,寻找我之前忘记的文件。 我根据 svn ls svn+ssh://mathe-svn/path 的输出创建的第一个文件列表,删除了我想保留的文件/目录。后来我不得不对旧版本重复此操作,因为之前一些文件被重命名(或更准确地说,整个目录树被移动),所以旧名称没有显示。此外,在当前修订版之前删除了一些文件。

现在我的 master 分支减少到 40 个修订,我的 HEAD 包含 39 个文件和目录。

存储库(只有在新存储库中克隆的这个分支)现在只有 180 KB 大(工作树为 288 KB)。我现在去清理提交评论(通常与这个项目毫无关系),然后将其发布到 github 上。


下一次,是否有一些命令可以创建我的存储库中曾经存在的所有文件路径的列表(无需检查所有修订并为每次调用find 或类似的)(git 或 svn 都可以。)

关于svn - 仅从 git 转换 subversion 存储库的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5385483/

相关文章:

SVN控制共享虚拟机文件夹

svn - 保持同一文件的多个副本同步的最佳方法是什么?

html - GitHub Pages (github.io) 找不到 doxygen 生成的页面 (404)

git:如何在不更改提交 ID 的情况下以非交互方式更改已提交的提交消息?

node.js - VSTS/TFS Build 仅在提交和推送 Git 标记时运行 NPM 任务

尽管已配置 Sourcetree,但 Git Bash 没有凭据

svn - TortoiseHG和hgsubversion(Windows): "no module named hgsubversion"

svn - 如何在不破坏任何内容的情况下替换 SVN 存储库中的目录

java - 如何使用SVN在线备份代码

git - 如何列出更改特定文件的所有提交?