将大型仓库拆分为多个子仓库并保留历史记录(Mercurial)

时间:2010-06-17 23:19:25

标签: visual-studio svn mercurial subrepos

我们有一大堆代码,在SVN的一个目录中包含多个共享项目,解决方案文件等。我们正在迁移到Mercurial。我想借此机会将我们的代码重新组织到几个存储库中,以便克隆分支的开销更少。我已经成功地将我们的回购从SVN转换为Mercurial,同时保留了历史。我的问题:如何在保留历史记录的同时将所有不同的项目分解为单独的存储库?

以下是我们的单一存储库(OurPlatform)目前的示例:

/OurPlatform
---- Core
---- Core.Tests
---- Database
---- Database.Tests
---- CMS
---- CMS.Tests
---- Product1.Domain
---- Product1.Stresstester
---- Product1.Web
---- Product1.Web.Tests
---- Product2.Domain
---- Product2.Stresstester
---- Product2.Web
---- Product2.Web.Tests
==== Product1.sln
==== Product2.sln

除解决方案文件外,所有这些文件夹都包含VS Projects。 Product1.sln和Product2.sln都引用了所有其他项目。理想情况下,我想采取每个文件夹,并将它们转换为单独的Hg回购,并为每个项目添加新的回购(它们将充当父回购)。然后,如果有人打算使用Product1,他们将克隆Product1 repo,其中包含Product1.sln和Subrepo对ReferenceAssemblies,Core,Core.Tests,Database,Database.Tests,CMS和CMS.Tests的引用。

因此,通过项目目录中的hg init'ing很容易做到这一点。但这可以在保存历史的同时完成吗?或者有更好的方法来安排这个吗?

EDIT ::::

感谢Ry4an的回答,我完成了目标。我想分享我在这里为其他人做的事情。

由于我们有很多单独的项目,我编写了一个小的bash脚本来自动创建文件图并创建最终的bat脚本来实际进行转换。从答案中不完全明显的是,convert命令需要为每个文件映射运行一次,以便为每个项目生成一个单独的存储库。此脚本将放在您先前转换的svn工作副本上方的目录中。我使用了工作副本,因为它的文件结构最符合我想要的最终新的hg repos。

#!/bin/bash

# this requires you to be in: /path/to/svn/working/copy/, and issue: ../filemaplister.sh ./

for filename in *
do
  extension=${filename##*.} #$filename|awk -F . '{print $NF}'
  if [ "$extension" == "sln" -o "$extension" == "suo" -o "$extension" == "vsmdi" ]; then
    base=${filename%.*}
    echo "#$base.filemap" >> "$base.filemap"
    echo "include $filename" >> "$base.filemap"
    echo "C:\Applications\TortoiseHgPortable\hg.exe convert --filemap $base.filemap ../hg-datesort-converted ../hg-separated/$base > $base.convert.output.txt" >> "MASTERGO.convert.bat"
  else
    echo "#$filename.filemap" >> "$filename.filemap"
    echo "include $filename" >> "$filename.filemap"
    echo "rename $filename ." >> "$filename.filemap"
    echo "C:\Applications\TortoiseHgPortable\hg.exe convert --filemap $filename.filemap ../hg-datesort-converted ../hg-separated/$filename > $filename.convert.output.txt" >> "MASTERGO.convert.bat"  
  fi  
done;

mv *.filemap ../hg-conversion-filemaps/
mv *.convert.bat ../hg-conversion-filemaps/

此脚本查看svn工作副本中的每个文件,并根据类型创建新的filemap文件或附加到现有文件。 if实际上只是为了捕获misc visual studio文件,并将它们放入一个单独的repo中。这是为了在bash上运行(在我的情况下是cygwin),但运行实际的转换命令是通过TortoiseHg附带的hg版本完成的,因为Windows上的分叉/进程问题(gah,我知道......)。

因此,您运行MASTERGO.convert.bat文件,该文件查看转换后的hg repo,并使用提供的文件映射创建单独的repos。完成后,有一个名为hg-separated的文件夹,其中包含每个项目的文件夹/存储库,以及每个解决方案的文件夹/存储库。然后,您必须手动将所有项目克隆到解决方案仓库中,并将克隆添加到.hgsub文件中。提交后,会创建一个.hgsubstate文件,你就可以开始了!

通过上面给出的示例,我的.hgsub文件对于“Product1”看起来像这样:

Product1.Domain = /absolute/path/to/Product1.Domain
Product1.Stresstester = /absolute/path/to/Product1.Stresstester
Product1.Web = /absolute/path/to/Product1.Web
Product1.Web.Tests = /absolute/path/to/Product1.Web.Tests

将这些存储库转移到中央服务器后,我将手动将路径更改为网址。

此外,最初的OurPlatform svn repo没有类似物,因为现在一切都已分开了。

再次感谢!

1 个答案:

答案 0 :(得分:28)

这绝对可以做到。您将需要使用hg convert命令。这是我使用的过程:

  1. 使用hg convert将所有内容转换为单个hg存储库,源类型为svn,目标类型为hg(听起来您已完成此步骤)
  2. 创建filemap个文件的集合,以便与hg convert的{​​{1}}选项一起使用
  3. 使用源类型--filemap和目标类型hg convert运行hg,并且源是在第一步中创建的mercurial repo - 并为您在步骤中创建的每个文件图执行此操作2。
  4. filemap语法显示在hg输出中,但这里是要点:

    hg help convert

    因此,在您的示例中,您的文件映射将如下所示:

    The filemap is a file that allows filtering and remapping of files and
    directories. Comment lines start with '#'. Each line can contain one of
    the following directives:
    
      include path/to/file
    
      exclude path/to/file
    
      rename from/file to/file
    

    请注意,如果您有一个包含,则隐含其他所有内容。此外,重命名行以点结尾,并将所有内容向上移动一级。

    # this is Core.filemap
    include Core
    rename Core .
    

    等等。

    为每个新仓库创建分解存储库后,您可以删除在步骤1中创建的has-everything初始仓库,并开始在# this is Core.Tests include Core.Tests rename Core.Tests . 个文件中设置子备份配置。