使用SubGit将svn转换为跨存储库重组的git

时间:2015-02-16 05:33:50

标签: git svn subgit

我正在尝试使用SubGit 2.0.3将Subversion存储库迁移到Git,同时尝试维护整个重组的完整历史记录。我的配置似乎保留了分支机构重组的历史,但不是主干。

重组本身有点......不寻常......并涉及中间布局。

初始布局:

  • trunk:/ ProjectOldName
  • branches:/ ProjectOldName / Releases
  • 标签:N / A

中级布局:

  • trunk:/ trunk / ProjectNewName
  • branches:/ releases / ProjectNewName
  • 标签:N / A

最终布局:

  • trunk:/ ProjectNewName / trunk
  • branches:/ ProjectNewName / branches / releases
  • 标签:/ ProjectNewName / tags

所以我用于转换的子映射是:

trunk = ProjectNewName/trunk:refs/heads/master
branches = trunk/ProjectNewName:refs/heads/old-master-interim
branches = ProjectOldName:refs/heads/old-master
branches = ProjectNewName/branches/releases/*:refs/heads/releases/*
branches = releases/ProjectNewName/*:refs/heads/old-releases-interim/*
branches = ProjectOldName/Releases/*:refs/heads/old-releases/*
tags = ProjectNewName/tags/*:refs/tags/*
shelves = ProjectNewName/shelves/*:refs/shelves/*

这保留了发布分支的历史记录,文件的日志将超出重组......虽然它似乎停止了分支的创建(在重组之前发生)。然而,在重组的最后一步和预期的“老主人 - 临时”的过程中,主人的同一档案的历史却停止了。和老主人'分支机构并不存在于git存储库中。

看起来重组是使用svn副本完成的(即,他们没有手动复制文件并重新提交它们),并且正确保留了最终布局的历史记录。中间布局创建了两次,第一次尝试被删除,注释表明历史未被保留。因此,尽管我可以告诉重组提交链(对于主干):

  • 从/ ProjectOldName
  • 开始
  • 添加目录/ trunk / ProjectNewName
  • 将多个目录(大多数但不是全部)添加到/ trunk / ProjectNewName / from / ProjectOldName /,并删除未添加的那些目录(如何发生这种情况我不确定,因为目录没有&t; t存在于那个分支中))
  • 在/ trunk / ProejctNewName / / ProjectOldName /中替换多个目录(上面添加的相同集合)(修改略有不同,可能是尝试重做以前的添加?)
  • 删除目录/ trunk / ProjectNewName(包含有关未保存历史记录的评论)
  • 添加目录/ trunk / ProjectNewName(第二次)
  • 将多个目录添加到/ trunk / ProjectNewName / from / ProjectOldName /,再次添加同一组目录,但这次删除不存在
  • 添加目录/ ProjectNewName / trunk
  • 将多个目录添加到/ ProjectNewName / trunk / from / trunk / ProjectNewName /
  • 删除目录/ trunk / ProjectNewName

它类似,但发布分支略有不同:

  • 从/ ProjectOldName / Releases
  • 开始
  • 添加目录/发布
  • 将多个目录(每个分支一个)添加到/ releases / from / ProjectOldName / Releases /
  • 删除目录/发布
  • 添加目录/版本/ ProjectNewName
  • 将多个目录(每个分支一个)添加到/ releases / ProjectNewName / from / ProjectOldName / Releases /
  • 添加目录/ ProjectNewName / branches / releases
  • 将多个目录(每个分支一个)添加到/ ProjectNewName / branches / releases / from / releases / ProjectNewName /
  • 删除目录/版本/ ProjectNewName

唯一真正的区别似乎是“替换多个目录”'发生在干线而不是树枝的步骤。

毕竟:

  • 有没有办法让SubGit转换上述内容,同时保持整个重组的历史记录?
  • SubGit可以在原始存储库布局中处理主干下的分支(即/ OldProjectName中的主干,/ OldProjectName / Releases中的分支)?
  • ' trunk'有什么特别的吗?映射?或者它实际上与“分支”没有什么不同。映射?对于svn和git来说,AFAIK对于' trunk'并没有什么特别之处。目录和'主人'分支。
  • 尽管分支机构的历史似乎可以跨越重组,但它们仍然停留在分支机构的创建上,而不是继续分支机构。是什么导致这种情况以及如何解决(如果可以的话)?

1 个答案:

答案 0 :(得分:1)

  

有没有办法让SubGit转换上述内容,同时保留中继重组的历史记录?

当整个分支目录从一个位置复制到另一个位置时,SubGit能够跟踪分支历史记录:

$ svn cp ^/trunk ^/branches/foo

但是,在复制某些分支子目录时,无法跟踪历史记录:

$ svn add ^/branches/foo
$ svn cp ^/trunk/dir1 ^/branches/foo/dir1
$ svn cp ^/trunk/dir2 ^/branches/foo/dir2
...
$ svn cp ^/trunk/dirN ^/branches/foo/dirN

不幸的是,这是对 ProjectOldName / trunk / ProjectNewName / ProjectNewName / trunk 目录进行重组的方式。因此,SubGit无法保留它们的历史记录。

在您的情况下,一种可能的解决方法是将这些目录导入单独的分支,然后使用git-replace将导入的片段移植到一个历史记录中。

然而,这种解决方法导致了下一个问题:

  

SubGit可以在原始存储库布局中处理主干下的分支(即/ OldProjectName中的主干,/ OldProjectName / Releases中的分支)吗?

不,在这种情况下,SubGit会忽略 OldProjectName 目录。

我们故意这样做:如果SubGit会尝试导入 OldProjectName 目录,那么任何向 OldProjectName / Releases 添加分支的修订都会花费很多时间,因为SubGit会对它进行处理作为一个全新的目录。

为了将 OldProjectName 历史记录移植到其他分支,我建议单独导入该分支:

$ subgit configure --svn-url URL REPO
$ git config -f REPO/subgit/config svn.trunk OldProjectName:refs/heads/master
$ subgit import REPO

之后,您可以将导入的更改提取到使用您已提到的设置导入的Git存储库,然后使用git replace加入 ProjectOldName / trunk / ProjectNewName <的历史记录/ em>和 / ProjectNewName / trunk

  

尽管分支机构的历史似乎可以跨越重组,但它们仍然停留在分支机构的创建上,而不是继续分支机构。什么会导致这种情况以及如何解决(如果可以的话)?

我认为这是由上一个问题引起的:由于 ProjectOldName 目录被忽略,SubGit无法保存复制的分支的历史记录,如下所示:

$ svn cp ^/ProjectOldName ^/ProjectOldName/Releases/BRANCH

不幸的是,这意味着您可以选择导入 ProjectOldName ProjectOldName / Releases / * 但不能同时导入。再次使用git replace可以通过嫁接分支的历史来帮助。

  

'trunk'映射有什么特别之处吗?或者它实际上与“分支”映射没有什么不同? svn和git的AFAIK分别对'trunk'目录和'master'分支没什么特别的。

trunk 分支配置选项之间的区别仅在Git到SVN导入期间有效。在将Git历史记录导入SVN时,SubGit会确保从第一个版本创建指定为 trunk 的分支,并且永远不会被删除或替换。指定为分支的分支在导入的SVN历史记录中的生命周期往往较短。

如果您将SVN历史记录导入Git, trunk 分支之间没有区别。

警告
如果您要保持Git和SVN存储库同步而不是执行一次性导入,则不应使用use git replace命令。

感谢您提供问题中的所有必要详细信息。希望我的回答足够有用。