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

时间:2011-03-22 00:47:03

标签: svn git

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

  • 躯干
    • 胶乳
    • 的java
      • AWT-铜工
      • PPS
        • 的build.xml
        • SRC
            • dclj
            • 常见问题
              • (约20个其他包裹)
              • ltxdoclet
                • (一些java文件)
    • LUA
    • (其他目录)
  • 分支
  • 标记
  • 进口
问题是我在这个存储库上做了很多重组 - 例如, pps 目录的所有内容都曾经在 import 的子目录中(我想我导入了它)来自CVS),也可能有其他动作。

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

我不想要这个存储库的其余部分(它们有时会得到单独的git存储库) - 这会使我的存储库过多爆炸(并且有一些我不想发布的东西)。

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

  • PPS
    • 的build.xml
    • SRC
        • 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个有一些有趣的树更改。 (由于我们的乳胶源文件首先位于latex目录中,因此大约有3个被错误地过滤掉了。)


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

2 个答案:

答案 0 :(得分:4)

这是我做的,供参考。


在Dustin的回答之后,我首先使用

将整个svn存储库转换为git
 git svn clone -A authors.txt svn+ssh://mathe-svn/ all-projects

这给了我一个非常庞大的git存储库,包含24241个对象和24 MB(打包后),来自45 MB的git存储库。正如已经说过的那样,两者在线性历史上都有2658次提交,所以直到现在都没有丢失。

然后,我开始从提供的过滤器过滤的东西出来... git filter-branch,{在{1}}一个似乎是最有用的,因为它并不需要签任何东西(相对于{ {1}}),我不想重写元数据,只删除不需要的文件。

此外,--index-filter也很有用。我还使用--tree-filter将工作目录放在tmpfs中,但我不知道这是否真的很重要,因为我在这里没有检查。我使用--prune-empty选项以新名称保存原始-d /dev/shm/ebermann/git-work/tmp引用。 (为什么--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分支减少到40个版本,我的HEAD包含39个文件和目录。

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


有关接下来的时间,的是有其产生的,其曾经在我的库中存在的所有文件的路径列表的一些命令(没有检查所有的修订出并且对于每个调用svn ls svn+ssh://mathe-svn/path,或这样)(对于git或svn都可以。)

答案 1 :(得分:3)

是的,了解filter-branch并在转化后进行所有修改。如果你弄错了,你可以逐步完成并反转每一步。