使用子git跨存储库重构将svn转换为git

使用子git跨存储库重构将svn转换为git,git,svn,subgit,Git,Svn,Subgit,我正在使用SubGit2.0.3将Subversion存储库迁移到Git,同时尝试在整个重构过程中维护完整的历史记录。我有一个配置,它似乎可以维护分支机构重组过程中的历史记录,但不能维护主干 重组本身有点…不寻常…涉及到中间布局 初始布局: trunk:/ProjectOldName 分支:/ProjectOldName/Releases 标签:不适用 中间布局: trunk:/trunk/ProjectNewName 分支:/releases/ProjectNewName 标签:不适用

我正在使用SubGit2.0.3将Subversion存储库迁移到Git,同时尝试在整个重构过程中维护完整的历史记录。我有一个配置,它似乎可以维护分支机构重组过程中的历史记录,但不能维护主干

重组本身有点…不寻常…涉及到中间布局

初始布局:

  • trunk:/ProjectOldName
  • 分支:/ProjectOldName/Releases
  • 标签:不适用
中间布局:

  • trunk:/trunk/ProjectNewName
  • 分支:/releases/ProjectNewName
  • 标签:不适用
最终布局:

  • trunk:/ProjectNewName/trunk
  • 分支:/ProjectNewName/branchs/release
  • 标签:/ProjectNewName/tags
因此,我用于转换的子Git映射是:

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/*
这维护了发布分支的历史记录,文件的日志将超出重组范围……尽管它似乎在分支创建时停止(在重组之前发生)。但是,在重建的最后一步创建时,master上相同文件的历史记录停止了,预期的“old master middial”和“old master”分支在git存储库中不存在

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

  • 以/ProjectOldName开始
  • 添加目录/trunk/ProjectNewName
  • 将多个目录(大多数,但不是全部)添加到/trunk/ProjectNewName/from/ProjectOldName/,并删除那些未添加的目录(我不确定这是如何发生的,因为该分支中还不存在这些目录)
  • 替换/trunk/ProejctNewName/from/ProjectOldName/(版本稍有不同,可能是尝试重做上一次添加?)
  • 删除目录/trunk/ProjectNewName(带有未保存历史记录的注释)
  • 添加目录/trunk/ProjectNewName(第二次)
  • 将多个目录添加到/trunk/ProjectNewName/from/ProjectOldName/,再次添加同一组目录,但这次没有删除
  • 添加目录/ProjectNewName/trunk
  • 将多个目录添加到/ProjectNewName/trunk/from/trunk/ProjectNewName/
  • 删除目录/trunk/ProjectNewName
这与发布分支类似,但略有不同:

  • 从/ProjectOldName/Releases开始
  • 添加目录/发布
  • 将多个目录(每个分支一个)添加到/releases/from/ProjectOldName/releases/
  • 删除目录/发布
  • 添加目录/releases/ProjectNewName
  • 将多个目录(每个分支一个)添加到/releases/ProjectNewName/from/ProjectOldName/releases/
  • 添加目录/ProjectNewName/branchs/releases
  • 将多个目录(每个分支一个)添加到/ProjectNewName/branchs/releases/from/releases/ProjectNewName/
  • 删除目录/releases/ProjectNewName
唯一真正的区别似乎是主干发生的“替换多个目录”步骤,而不是分支

因此,在所有这些之后:

  • 有没有一种方法可以让SubGit转换上述内容,同时在主干的重组过程中维护历史记录
  • SubGit能否像原始存储库布局中那样处理主干下的分支(即主干位于/OldProjectName,分支位于/OldProjectName/release)
  • “主干”映射有什么特别之处吗?或者它实际上与“分支”映射没有什么不同?对于svn和git来说,‘trunk’目录和‘master’分支没有什么特别之处
  • 尽管分支上的历史似乎跨越了重组OK,但它们在分支创建时停止,而不是继续分支的起点。这是什么原因造成的?如何修复(如果可以的话)
有没有一种方法可以让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无法为他们保存历史记录

在您的案例中,一个可能的解决方法是将这些目录导入到单独的分支中,然后使用将导入的片段移植到一个单独的历史中

但是,这种解决方法会导致下一个问题:

SubGit能否像原始存储库布局中那样处理主干下的分支(即主干位于/OldProjectName,分支位于/OldProjectName/release)

不,在这种情况下,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和/ProjectNewName/trunk的历史记录

尽管树枝上的历史似乎
$ svn cp ^/ProjectOldName ^/ProjectOldName/Releases/BRANCH