如何克隆SVN存储库的一部分?

时间:2010-07-03 07:25:48

标签: svn svndump svndumpfilter

我有一个SVN存储库,里面有很多目录。现在我想克隆这个存储库,只留下一个特定的目录。当然,我不需要在这个新存储库中与其他目录相关的任何修订。我该怎么做?感谢。

3 个答案:

答案 0 :(得分:5)

您需要创建存储库的转储,并过滤掉所需的目录和修订。 svndumpfilter是用于此目的的通用工具。有关示例,请参阅this chapter of the subversion book

答案 1 :(得分:0)

另一种可能性是git svn clone,它只提取感兴趣的目录。然后可以将其推送到新的svn仓库。这简单吗?不,但如果您无法访问服务器,则非常方便。我确信有更好的方法 - 但这样可以确保您不会意外地推送到原始的svn回购。


    # original svn path
    git svn clone http://server/path/to/clone orig
    # SVN to put just your branch in
    svnadmin create new
    # add one entry, or git svn errors out...
    svn co file:///path/to/new new.wd
    mkdir new.wd/null
    svn add new.wd/null
    svn ci -m"add null" new.wd/null
    # clone our clone
    git clone file:///path/to/orig abc
    cd abc
    # set up svn path to the svn repo
    git svn init file:///path/to/new
    # pull data in (our one commit)
    git svn fetch
    # show the branches
    git branch -a
    # Prep the git repot for the push
    git rebase --onto remotes/git-svn --root master
    # finally push to the new svn repo.
    git svn dcommit

不知道我在哪里可以找到这个,所以我想出了这个。您可能需要像这样混乱svn donf文件:


    svn_repo="$(pwd)/new"
    user="myusername"
    echo '[/]' >> $svn_repo/conf/authz
    echo "$user = rw" >> $svn_repo/conf/authz
    echo '[users]' >> $svn_repo/conf/passwd
    echo "$user = test" >> $svn_repo/conf/passwd
    echo 'password-db = passwd' >> $svn_repo/conf/svnserve.conf
    echo "svn repo is file://$svn_repo"
    svn co file://$svn_repo svn.wd

在上面的示例中,myusername的密码为test。

答案 2 :(得分:0)

执行您尝试执行的操作的传统方法是将存储库转储到转储文件,使用svndumpfilter根据需要包含或排除文件,然后将筛选的转储文件加载到新存储库中。这种方法适用于简单的更改,例如从存储库中删除几个文件。

当存储库包含文件移动和副本时,事情变得更加困难。

让我们举一个最简单的示例,即将历史记录中某个名为MyProject的项目文件夹重命名为TheProject。另一个名为TheProject/copiedfile.txt的文件随后从位置TheProject复制到AnotherLocation下。一个基本的树结构可能看起来像这样。

...
+ AnotherLocation
|--- copiedfile.txt
|--- unwantedfile.txt
+ TheProject
|--- copiedfile.txt
|--- otherfile.txt 
...

您希望TheProject拥有自己的新存储库。因此,您将存储库转储到文件并使用svndumpfilter仅包含TheProject,因为这是您在HEAD修订版中看到的项目的名称。

svndumpfilter include /TheProject < input.dump > output.dump

您很遗憾从svndumpfilter

收到此错误
svndumpfilter: E200003: Invalid copy source path '/MyProject'

多数民众赞成因为TheProject过去曾被称为MyProject,而在过去的某些修订中,它已被重命名。由于重命名本质上是一个删除和复制,因此svndumpfilter无法找到创建TheProject的副本的来源,并且正确地出现错误。因此,我们再次尝试使用包含MyProject以及

的以下命令
svndumpfilter include /TheProject /MyProject < input.dump > output.dump

Svndumfilter现在又出现了另一个错误。

svndumpfilter: E200003: Invalid copy source path '/AnotherLocation/copiedfile.txt'

是的,这是因为copiedfile.txt已从AnotherLocation复制到TheProject。因此我们必须包含此文件,否则我们无法将其复制到“TheProject&#39;”。让我们再试一次。

svndumpfilter include /TheProject /MyProject /AnotherLocation/copiedfile.txt < input.dump > output.dump

操作成功!第三次幸运似乎!

让我们尝试将过滤后的转储文件加载到存储库。

svnadmin create newrepo
svnadmin load newrepo < output.dump

毕竟没那么幸运!加载

时出现以下错误
* editing path : AnotherLocation/copiedfile.txt ...svnadmin: E160013: File not found: transaction '1-1', path '/AnotherLocation/copiedfile.txt'

啊!这是因为我们忘记包含AnotherLocation这是必需的,因为它是copiedfile.txt

的父文件夹
svndumpfilter include /TheProject /MyProject /AnotherLocation < input.dump > output.dump

确定此命令有效,加载也有效。不幸的是,我们现在也包含了/AnotherLocation/unwantedfile.txt。结论是使用svndumpfilter include并不真正起作用,因为它没有给出我们所追求的粒度。我们必须使用svndumpfilter exclude执行所有操作,以尝试排除我们不需要的所有内容,从而最终获得包含所需文件的存储库。可以说,它充满了自己的一系列问题。例如,可以很容易地排除存储库中实际需要的文件。如果人们想要一个这样的例子,我可以扩展这个答案。

必须有更好的方法。事实证明,但这是一个商业产品。我们开发了一个名为Subdivision的工具,专门从subversion存储库中提取文件和文件夹。它还可以从subversion存储库中删除(或删除)文件,以及将存储库拆分为两部分,同时保证不会从两个存储库之一中遗漏任何文件。 Subdivision的亮点在于它拥有整个存储库的内存视图,并运行解决上述示例中遇到的所有问题所需的算法。这意味着您只需在保存用户时间的同时获取正确文件的必要粒度,因为操作在一次传递中完成。