我有一个旧的 Subversion 存储库,里面有很多我的私有(private)项目。它的一部分是几年前从一个旧的 CVS 存储库(使用 cvs2svn 或类似的)转换而来的。它当前的结构如下所示:
- 后备箱
- latex
- java
- awt独库
- 页数
- build.xml
- 来源
- Ant
- 德
- dclj
- 常见问题
- 保罗
- (大约 20 个其他包)
- ltxdoclet
- (一些java文件)
- 路亚
- (其他目录)
- 分支机构
- 标签
- 导入
我现在对 ltxdoclet 目录的内容以及路径中的一些其他文件感兴趣,例如 build.xml、ant 目录等。我想拥有他们的全部历史记录,包括移动文件之前的任何历史记录。我现在想把它作为一个 git 存储库(因为我想在 github 上发布它)。标签和分支从未真正使用过,所以它们并不重要。
我不想要这个存储库的其余部分(他们有时会得到单独的 git 存储库)——这会把我的存储库炸得太多(有些东西我不想发布)。
理想情况下,我生成的 git 存储库(处于 HEAD 状态)应该如下所示:
- 页数
- build.xml
- 来源
- Ant
- 德
- dclj
- 保罗
- ltxdoclet
- (一些java文件)
- ltxdoclet
- 保罗
- dclj
当然,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/