一尘不染

如何将具有历史记录的 SVN 存储库迁移到新的 Git 存储库?

javascript

我阅读了 Git 手册、常见问题解答、Git - SVN 速成课程等,它们都解释了这个和那个,但是你在任何地方都找不到像这样的简单说明:

SVN 存储库位于:svn://myserver/path/to/svn/repos

Git 存储库位于:git://myserver/path/to/git/repos

git-do-the-magic-svn-import-with-history \
svn://myserver/path/to/svn/repos \
git://myserver/path/to/git/repos

我不希望它那么简单,也不希望它是一个命令。但我确实希望它不会试图解释任何事情 - 只是说给出这个例子要采取的步骤。


阅读 135

收藏
2022-02-22

共1个答案

一尘不染

创建users.txt用于将 SVN 用户映射到 Git 的用户文件(即 ):

user1 = First Last Name <email@address.com>
user2 = First Last Name <email@address.com>
...

您可以使用此单线从现有的 SVN 存储库构建模板:

svn log -q | awk -F '|' '/^r/ {gsub(/ /, "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt

如果 SVN 发现丢失的 SVN 用户,而不是在文件中,它将停止。但在那之后,您可以更新文件并从上次中断的地方继续。

现在从存储库中提取 SVN 数据:

git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp

此命令将在其中创建一个新的 Git 存储库dest_dir-tmp并开始拉取 SVN 存储库。请注意,“–stdlayout”标志意味着您具有通用的“主干/、分支/、标签/”SVN 布局。如果您的布局不同,请熟悉--tags--branches--trunk选项(通常git svn help)。

允许所有常用协议:svn://, http://, https://. URL 应该以基本存储库为目标,例如http://svn.mycompany.com/myrepo/repository。URL 字符串不能包含/trunk,/tag/branches

请注意,执行此命令后,经常会出现操作“挂起/冻结”的情况,并且在初始化新存储库后可能会卡住很长时间是很正常的。最终,您将看到指示它正在迁移的日志消息。

另请注意,如果您省略该--no-metadata标志,Git 会将有关相应 SVN 修订的信息附加到提交消息(即git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>

如果未找到用户名,请更新您的users.txt文件,然后:

cd dest_dir-tmp
git svn fetch

如果您有一个大型项目,直到获取所有 Subversion 提交,您可能需要多次重复最后一个命令:

git svn fetch

完成后,Git 会将 SVN 检出trunk到新分支中。任何其他分支都设置为远程。您可以通过以下方式查看其他 SVN 分支:

git branch -r

如果要在存储库中保留其他远程分支,则需要手动为每个分支创建一个本地分支。(跳过trunk/master。)如果你不这样做,分支将不会在最后一步被克隆。

git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same names

标签作为分支导入。您必须创建一个本地分支,创建一个标签并删除该分支才能将它们作为 Git 中的标签。使用标签“v1”来做到这一点:

git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1

将您的 GIT-SVN 存储库克隆到一个干净的 Git 存储库中:

git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir

您之前从远程分支创建的本地分支只会作为远程分支复制到新克隆的存储库中。(跳过trunk/master。)对于您要保留的每个分支:

git checkout -b local_branch origin/remote_branch

最后,从干净的 Git 存储库中删除指向现在已删除的临时存储库的远程:

git remote rm origin
2022-02-22