将多个 svn 存储库迁移到单个 git 存储库中

Shy*_*yru 5 svn migration version-control git

我们希望从 svn 永久迁移到 git,以便能够在分支和协作方面使用 git 更好的功能。

我们当前的 svn 存储库看起来像这样

svnrepo/
   frontend/
      trunk
      branches/
         ng/
         ...
      tags/
         1.x
         ...
   backend/
      trunk
      branches/
         ng/
         ...
      tags/
         1.x
         ...
Run Code Online (Sandbox Code Playgroud)

工作布局是我们检出前端项目,并在其中创建一个后端文件夹并检出后端项目。

我们现在想迁移到 git,并放弃前端和后端之间的拆分(就独立项目而言),因为它给我们带来的问题多于优势。我们希望它们都在一个 git 存储库中。

我想使用svn2git进行转换。不幸的是,最新的开发都发生在一个分支中,而不是在主干中,但我认为这对于 svn2git 来说应该不是问题。因此,新的 git 存储库布局应如下所示:

/            => svnrepo/frontend/branches/ng
/backend     => svnrepo/backend/branches/ng
Run Code Online (Sandbox Code Playgroud)

其中 => 表示“迁移/转换自”。

对于转换,我们没有必要将 svn 存储库中的所有标签和分支转换为 git。这对我们来说并不重要。然而重要的是,我们拥有所有提交到分支/ng 目录中的所有文件的完整历史记录,返回到主干分支以及之前发生在主干中的所有提交。我们希望所有这些提交都在单个 git 存储库中具有上述布局。这甚至可能吗?我们将如何做到这一点?

我已经在 google 和 stackoverflow 12 中进行了搜索,但找不到我们问题的确切解决方案。

小智 5

一种解决方案是使用 svn2git 单独生成每个存储库或仅生成git svn(这是一个已经内置到 git 中的不错的小工具),然后将它们与git filter-branch.

  1. 单独克隆每个 svn 存储库。
  2. 在您想要成为 root 的存储库中,将其他存储库添加为远程存储库,并获取要合并到该存储库的分支(您将收到警告,因为这些分支没有共同的历史记录;这是预期的)。
  3. git filter-branch在这些新分支上执行,使用索引过滤器为它们生成新的子目录。
  4. 将过滤后的分支合并到master根存储库上(或您想要的任何分支)。完整的历史将被保留。

第 3 步的命令如下所示:

git filter-branch --index-filter '
    git ls-files -s |
    perl -pe "s{\t\"?}{$&newsubdir/}" |
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
    mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD
Run Code Online (Sandbox Code Playgroud)

魔术,每次我必须这样做时,它确实感觉有点像魔术,就是perl声明。在每次提交时git filter-branch过滤索引所有 blob 路径(即更改工作树的文件路径)之前添加“newsubdir”。您可能需要反复试验才能使路径完全正确。从以前走过这条路的人那里吸取了一些教训

  • 备份一切。 git filter-branch是历史破坏性的。一旦你改变了它,你就不能轻易地把它改回来。请务必备份您正在使用的所有存储库副本。没有什么比完成复杂的操作并发现您/在路径中错过了更糟糕的了。
  • 脚本一切。除非你有一些严肃的技能;你不会第一次就做对。在您完成每个单独的步骤时编写脚本,以便轻松重新运行其中任何一个步骤。此外,如果您在一周后发现自己搞砸了一面旗帜,您可以立即复制。
  • 在 EC2 中的集群计算实例上花费 20 美元。 git filter-branch是极大的 CPU 密集型。深度历史的索引过滤器可能需要数小时才能在您的本地环境中运行,但在 AWS集群计算实例上只需要一小部分时间当然,它们每小时的成本略高于 2 美元,但您只需要几个小时即可。省去自己的痛苦,并使用您在硬件上编写的脚本,使操作变得微不足道。它花费了一顿美味午餐的价格。