如何将 SVN 转换为 GIT,同时将一个巨大的存储库拆分为单独的存储库?

How can I convert SVN to GIT while splitting one huge repository into separate repositories?

我想将我们的 SVN 存储库迁移到 git

我们当前的存储库是一个巨大的单例堆,包含许多 Visual Studio 解决方案,所有解决方案都位于存储库的单独子目录中。

将其转换为 git 时,我想将 SVN 存储库拆分为每个解决方案的单独 git 存储库,同时维护每个解决方案的历史记录。

我不想在我们所有未来的 git 存储库中包含整个 SVN 存储库的历史记录。在这些未来的 git 存储库中,我只想要特定子目录的历史记录。

这可能吗?


当前 SVN 存储库文件结构:

svn_base
   |-- Solution1
   |   |-- 1.cs
   |   |-- 1.csproj
   |   |-- 1.sln
   |-- Solution1
   |   |-- 2.cs
   |   |-- 2.csproj
   |   |-- 2.sln
   |-- Solution3
   |   |-- 3.cs
   |   |-- 3.csproj
   |   |-- 3.sln

所需的git存储库文件结构:

Solution1
   |-- .git
   |-- 1.cs
   |-- 1.csproj
   |-- 1.sln

Solution2
   |-- .git
   |-- 2.cs
   |-- 2.csproj
   |-- 2.sln


Solution3
   |-- .git
   |-- 3.cs
   |-- 3.csproj
   |-- 3.sln

如果你的项目被整齐地分成它们自己的子目录,这应该是非常简单的使用 --trunk parametergit svn init/git svn clone:

git svn clone --trunk=Solution1 $SVN_URI ./Solution1

这会将子文件夹 Solution1 的唯一历史克隆到目录 ./Solution1 中的新 git 存储库中。它将只包含涉及该子文件夹中文件的提交,并且它会调整相对路径,以便该子文件夹是新 git 存储库的根目录。

虽然@acran 给出的答案确实解决了问题,但也可以先将 SVN 存储库转换为 Git,然后将大的 monorepo 拆分为多个较小的存储库。

1。将 SVN 转换为 Git

如果您的 SVN 存储库具有标准布局(子目录 branchestagstrunk)并且您不需要任何其他附加功能,这很容易:

$ git svn clone <url_to_subversion_repo>

这个命令有两个陷阱:

  1. git svn 使用 SVN 登录作为 Git 作者姓名。它还使用一些默认邮件地址(@localhost,我想,虽然我不确定)。如果这不是您想要的,您可以使用作者文件。添加文件 user_mapping.txt 将 SVN 用户映射到 git 用户:
    svn_user_1 = Git User 1 <user1@example.com>
    svn_user_2 = Git User 2 <user2@example.com>
    
    然后用这个文件调用 git svn clone
    $ git svn clone --authors-file=user_mapping.txt <url_to_subversion_repo>
    
  2. 由于 SVN 标签可以更改,git svn 将它们导入为 Git 分支。 If you want, you can convert them.

git svn clone 从 SVN 服务器按顺序检查你的 SVN 仓库的每个修订版——如果你有一个大仓库,这将需要一段时间(我的经验是大约 50,000 次修订需要多个小时,我认为,虽然我不确定,这是几年前的事了)。如果可能,您可能希望在 SVN 服务器上 运行 此命令,尤其是在连接速度较慢的情况下。无论哪种方式,去喝杯咖啡(或五杯)。

2。拆分 Git 存储库

有多种工具可以将 Git 存储库拆分为子存储库。参见示例 this question. When I did this a few years ago, I used git filter-branch, but this tool is now deprecated – you may still use it, or you may use git filer-repo,尽管我没有使用此工具的任何经验。

我链接的问题的最受支持的答案使用 git subtree filter – 我建议 不要 使用这个答案,因为 git subtree filter 只转换一个分支,实际上从您的子存储库中删除所有其他分支。

优势

与通过 git svn clone 转换每个子存储库相比,此答案的优势是什么?

  • 您只需克隆 SVN 存储库一次。这可能比为每个项目克隆子文件夹更快(虽然我没有测试过,这只是一个有根据的猜测)。
  • 克隆具有标准布局的 SVN 存储库比克隆具有非标准布局的 SVN 存储库经过更好的测试。根据我的经验,git svn 并不总是按照您的意愿行事,因此更标准的用法可能更有可能产生您想要的结果。
  • 如果您想重写新 Git 存储库的历史记录(例如,删除大型二进制文件),您可以在第一步和第二步之间重写 monorepo 的历史记录。为每个新的子存储库执行此操作将需要更大的努力。