29

我们有一个庞大的代码库,在 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 项目的文件夹。Product1.sln 和 Product2.sln 都引用了所有其他项目。理想情况下,我想把这些文件夹中的每一个都变成单独的 Hg 存储库,并为每个项目添加新的存储库(它们将充当父存储库)。然后,如果有人要在 Product1 上工作,他们将克隆 Product1 存储库,其中包含 Product1.sln 和对 ReferenceAssemblies、Core、Core.Tests、Database、Database.Tests、CMS 和 CMS.Tests 的子存储库引用。

因此,只需在项目目录中进行 hg init'ing 即可轻松完成此操作。但可以在保留历史的同时做到吗?或者有没有更好的方法来安排这个?

编辑::::

感谢 Ry4an 的回答,我能够实现我的目标。我想在这里为其他人分享我是如何做到的。

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

#!/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 工作副本中的每个文件,并根据类型创建新的文件映射文件或附加到现有文件。if 实际上只是为了捕获 misc visual studio 文件,并将它们放入单独的 repo 中。这意味着要在 bash(在我的情况下为 cygwin)上运行,但由于 Windows 上的分叉/进程问题,运行实际的转换命令是通过 TortoiseHg 附带的 hg 版本完成的(哎呀,我知道......)。

因此,您运行 MASTERGO.convert.bat 文件,该文件查看转换后的 hg 存储库,并使用提供的文件映射创建单独的存储库。完成后,有一个名为 hg-separated 的文件夹,其中包含每个项目的文件夹/repo,以及每个解决方案的文件夹/repo。然后,您必须手动将所有项目克隆到解决方案存储库中,并将克隆添加到 .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

将这些存储库传输到中央服务器后,我将手动将路径更改为 url。

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

再次感谢!

4

1 回答 1

28

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

  1. 使用 svn 的源类型和 hg 的 dest 类型将所有内容转换为单个 hg 存储库hg convert(听起来你已经完成了这一步)
  2. filemap使用hg convert's--filemap选项创建文件集合
  3. hg convert使用源类型hg和目标类型运行,源hg是在第一步中创建的 mercurial 存储库 - 并为您在第二步中创建的每个文件映射执行此操作。

文件映射语法显示在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 .

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

# this is Core.Tests
include Core.Tests
rename Core.Tests .

等等。

为每个新存储库创建分解存储库后,您可以删除在第一步中创建的 has-everything 初始存储库并开始在.hgsub文件中设置子存储库配置。

于 2010-06-18T03:35:13.817 回答