我想把我们的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
虽然@acran给出的答案确实解决了问题,但首先将SVN存储库转换为Git,然后将大的单一存储库拆分为多个较小的存储库也是可能的,有时也是有利的。
1。转换SVN到Git
如果你的SVN存储库有一个标准的布局(子目录branches
,tags
和trunk
),你不需要任何其他的花哨的东西,这是很容易的:
$ git svn clone <url_to_subversion_repo>
这个命令有两个陷阱:
git svn
使用SVN登录名作为Git作者名。它还使用一些默认的邮件地址(我想是@localhost,尽管我不确定)。如果这不是您想要的,您可以使用authors文件。添加SVN用户到git用户的映射文件 user_mapping.txt
。
然后用这个文件调用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分支导入。如果你愿意,你可以转换它们。
git svn clone
按顺序从SVN服务器检查出SVN repo的每个版本-如果您有一个大的存储库,这将需要一段时间(我的经验是,大约50,000个版本需要多个小时,我想,尽管我不确定,这是几年前的事情)。如果可能,您可能希望在SVN服务器上运行该命令,特别是在连接速度较慢的情况下。不管怎样,去喝杯咖啡(或五杯)。
2。拆分Git存储库
有多个工具可以将Git库拆分为子库。请看下面这个问题。当我几年前这样做的时候,我用的是git filter-branch
,但是这个工具现在已经被弃用了——你可以仍然使用它,或者你可以使用git filer-repo
,尽管我没有任何使用这个工具的经验。
对我链接的问题的最多支持的答案使用git subtree filter
-我建议而不是使用这个答案,因为git subtree filter
只转换一个分支,实际上是从子存储库中删除所有其他分支。
优势与通过git svn clone
转换每个子存储库相比,这个答案的优点是什么?
- 您只需要克隆SVN存储库一次。这可能比克隆每个项目的子文件夹要快(尽管我没有测试过,这只是一个有根据的猜测)。
- 克隆具有标准布局的SVN存储库比克隆具有非标准布局的SVN存储库更好。根据我的经验,
git svn
并不总是做你想要的,所以一个更标准的用法可能更有可能产生你想要的结果。 - 如果您想重写新Git存储库的历史记录(例如,删除大的二进制文件),您可以在步骤1和步骤2之间重写monorepo的历史记录。对于每一个新的子存储库,这将是一个更大的努力。
如果您的项目被整齐地划分到它们自己的子目录中,那么使用--trunk
参数到git svn init
/git svn clone
应该是非常直接的:
git svn clone --trunk=Solution1 $SVN_URI ./Solution1
这将把Solution1
子文件夹的唯一历史文件克隆到./Solution1
目录下的新git存储库中。它将只包含涉及该子文件夹中的文件的提交,并且它将调整相对路径,使该子文件夹成为新git存储库的根目录。