如何在将一个巨大的存储库拆分为单独的存储库时将 SVN 转换为 GIT?
Posted
技术标签:
【中文标题】如何在将一个巨大的存储库拆分为单独的存储库时将 SVN 转换为 GIT?【英文标题】:How can I convert SVN to GIT while splitting one huge repository into separate repositories? 【发布时间】:2021-10-04 11:42:24 【问题描述】:我想将我们的 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
【问题讨论】:
使用 git-svn,您可以告诉它主干在哪里(也是您保存分支/标签的目录),因此将每个项目分成自己的单独 git 存储库应该没有问题。 你也可以先convert SVN to Git,然后split your history in different repositories。 我不确定该工具在将 SVN 转换为 Git 并在那里拆分方面有多好 - 也许它很棒。但我知道新的 git-filter-repo 工具很棒,所以如果是我,我会选择 @sk_pleasant-EliasHolzmann 的建议,先将 SVN 转换为一个大的 Git 存储库,然后使用 git-filter-repo 其余的. 作为旁注,在不了解您的代码库的情况下,我的直觉是每个 repo 的一个解决方案对于 repo 来说可能有点细化。您没有说明为什么要拆分,但是除非每个都太大,或者您的分类限制某些人查看某些代码,否则我可能会将其留在一个仓库中,直到我有充分的理由拆分出来。 (也许你会。) @sk_pleasant-EliasHolzmann:很好的提示!我尝试了一个示例存储库,git subtree
就像一个魅力。 (不幸的是,这个命令的手册页似乎不见了。) - 如果你想发表你的评论作为答案,我很乐意投票。
【参考方案1】:
虽然@acran 给出的答案确实解决了这个问题,但首先将 SVN 存储库转换为 Git,然后将大型 monorepo 拆分为多个较小的存储库也是可能的,有时也是有利的。
1. SVN转Git
如果您的 SVN 存储库具有标准布局(子目录 branches
、tags
和 trunk
)并且您不需要任何其他花里胡哨,这很容易:
$ git svn clone <url_to_subversion_repo>
这个命令有两个陷阱:
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>
由于 SVN 标签可以更改,git svn
将它们作为 Git 分支导入。 If you want, you can convert them。
git svn clone
按顺序从 SVN 服务器检查您的 SVN 存储库的每个修订版 - 如果您有一个大存储库,这将需要一段时间(我的经验是大约 50,000 次修订需要几个小时,虽然我是不确定,这是几年前的事了)。如果可能,您可能希望在 SVN 服务器上运行此命令,尤其是在连接速度较慢的情况下。不管怎样,去喝杯咖啡(或五杯)。
2.拆分 Git 存储库
有多种工具可以将 Git 存储库拆分为子存储库。参见例如this question。几年前我这样做的时候,我使用了git filter-branch
,但是这个工具现在已经被弃用了——你可以继续使用它,或者你可以使用git filer-repo
,尽管我没有使用这个工具的任何经验。
对我链接的问题的最赞成的答案使用git subtree filter
- 我建议不要使用这个答案,因为git subtree filter
只转换一个分支,实际上从您的子存储库中删除所有其他分支.
优势
与通过git svn clone
转换每个子存储库相比,此答案有什么优势?
git svn
并不总是按照您的意愿行事,因此更标准的用法可能更有可能产生您想要的结果。
如果您想重写新 Git 存储库的历史记录(例如,删除大的二进制文件),您可以在第一步和第二步之间重写 monorepo 的历史记录。为每个新的子存储库执行此操作会付出更大的努力。
【讨论】:
【参考方案2】:如果您的项目被整齐地分隔到它们自己的子目录中,那么使用--trunk
parameter 到git svn init
/git svn clone
应该非常简单:
git svn clone --trunk=Solution1 $SVN_URI ./Solution1
这会将子文件夹Solution1
的唯一历史克隆到目录./Solution1
中的新git 存储库中。它只会包含涉及该子文件夹中文件的提交,并且会调整相对路径,使子文件夹成为新 git 存储库的根目录。
【讨论】:
很好的答案!我目前正在执行您的建议。在我投票之前等待结果。我应该注意 - 在 Windows 上 - 主干名称应该用正斜杠而不是反斜杠给出,即--trunk MySubDir/Solution1
。以上是关于如何在将一个巨大的存储库拆分为单独的存储库时将 SVN 转换为 GIT?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Tortoisesvn 创建新的 SVN 存储库时如何设置存储库路径