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

我阅读了 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

我不希望它那么简单,也不希望它是单个命令。但我确实希望它不会尝试解释任何内容 - 仅说明在此示例中应采取的步骤。

答案

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

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

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

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $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

该命令将在dest_dir-tmp创建一个新的 Git 存储库,并开始提取 SVN 存储库。请注意,“-stdlayout” 标志表示您具有通用的 “trunk /,branchs /,tags /” SVN 布局。如果您的布局不同,熟悉--tags--branches--trunk选项(一般git svn help )。

允许所有通用协议: svn://http://https:// 。该 URL 应该以基本存储库为目标,例如http://svn.mycompany.com/myrepo/repository 。那不能包括/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

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

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

标签被导入为分支。您必须创建一个本地分支,创建一个标签并删除该分支,以使其成为 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

您先前从远程分支创建的本地分支将仅作为远程分支复制到新的克隆存储库中。 (跳过中继 / 主机。)对于要保留的每个分支:

git checkout -b local_branch origin/remote_branch

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

git remote rm origin

魔法:

$ git svn clone http://svn/repo/here/trunk

Git 和 SVN 的操作非常不同。您需要学习 Git,如果您想从 SVN 上游跟踪更改,则需要学习git-svngit-svn 主页上有一个很好的示例部分

$ git svn --help

将 Subversion 仓库干净地迁移到 Git 仓库 。首先,您必须创建一个文件,将您的 Subversion 提交作者名称映射到 Git 提交者,例如~/authors.txt

jmaddox = Jon Maddox <jon@gmail.com>
bigpappa = Brian Biggs <bigpappa@gmail.com>

然后,您可以将 Subversion 数据下载到 Git 存储库中:

mkdir repo && cd repo
git svn init http://subversion/repo --no-metadata
git config svn.authorsfile ~/authors.txt
git svn fetch

如果您使用的是 Mac,则可以通过安装git-core +svn从 MacPorts 获得git-svn git-core +svn

如果您的 Subversion 信息库与所需的 git 信息库位于同一台计算机上,则可以将此语法用于 init 步骤,否则全部相同:

git svn init file:///home/user/repoName --no-metadata

我使用了svn2git 脚本,并且像一个吊饰一样工作。

我建议在尝试不断使用 git-svn 之前先熟悉一下 Git,即保持 SVN 作为集中存储库并在本地使用 Git。

但是,对于包含所有历史记录的简单迁移,以下是几个简单步骤:

初始化本地仓库:

mkdir project
cd project
git svn init http://svn.url

标记您要开始导入修订版本的时间:

git svn fetch -r42

(或仅对所有版本使用 “git svn fetch”)

从那时起实际上获取了所有东西:

git svn rebase

您可以使用 Gitk 检查导入结果。我不确定这是否适用于 Windows,适用于 OSX 和 Linux:

gitk

在本地克隆 SVN 存储库后,您可能需要将其推送到集中式 Git 存储库中,以简化协作。

首先创建您的空远程仓库(也许在GitHub 上 ):

git remote add origin git@github.com:user/project-name.git

然后,有选择地同步您的主分支,以便当两者都包含新内容时,拉取操作将自动将远程主服务器与本地主服务器合并:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

之后,您可能有兴趣尝试使用我自己的git_remote_branch工具,该工具有助于处理远程分支:

第一个说明性文章:“ Git 远程分支机构

最新版本的后续跟踪:“ git 与 git_remote_branch 合作的时间

有一个新的解决方案可以平稳地从 Subversion 迁移到 Git(或同时使用): SubGit

我自己在做这个项目。我们在存储库中使用 SubGit - 我的一些队友使用 Git 和一些 Subversion,到目前为止,它运行良好。

要使用 SubGit 从 Subversion 迁移到 Git,您需要运行:

$ subgit install svn_repos
...
TRANSLATION SUCCESSFUL

之后,您将在 svn_repos / .git 中获得 Git 存储库并可以克隆它,或者只是继续将 Subversion 和这个新的 Git 存储库一起使用:SubGit 将确保两者始终保持同步。

如果您的 Subversion 存储库包含多个项目,则将在 svn_repos / git 目录中创建多个 Git 存储库。要在运行翻译之前自定义翻译,请执行以下操作:

$ subgit configure svn_repos
$ edit svn_repos/conf/subgit.conf (change mapping, add authors mapping, etc)
$ subgit install svn_repos

使用SubGit,您可以迁移到纯 Git(而不是 git-svn)并开始使用它,同时只要需要就可以保留 Subversion(例如,对于已经配置的构建工具)。

希望这可以帮助!

请参阅git-svn官方手册。特别是,在 “基本示例” 下查看:

跟踪并为整个 Subversion 管理的项目(包括主干,标签和分支完成)做出贡献:

# Clone a repo (like git clone):
    git svn clone http://svn.foo.org/project -T trunk -b branches -t tags

SubGit (与死亡蓝屏相对)

subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

就是这样

+ 要从 SVN 更新,这是第一个命令创建的 Git 存储库。

subgit import  directory/path/Local.git.Repo

我使用了一种快速迁移到 Git 的方法来存储庞大的存储库。
当然你需要一些准备。
但是,您可能根本不会停止开发过程。

这是我的方式。

我的解决方案如下所示:

  • 将 SVN 迁移到 Git 存储库
  • 在团队切换到之前更新 Git 存储库

大型 SVN 存储库的迁移需要大量时间。
但是更新完成的迁移只需几秒钟。

当然,我正在使用SubGit ,妈妈。 git-svn 使我蓝死了 。只是不断。 git-svn 让 Git 的 “ 文件名过长 ” 致命错误使我感到无聊。

脚步

1. 下载 SubGit

2.准备迁移和更新命令。

假设我们是在 Windows 上完成的(移植到 Linux 并不容易)。
在 SubGit 的安装bin目录(subgit-2.XX \ bin)中,创建两个. bat 文件。

迁移文件 / 命令的内容:

start    subgit import --svn-url url://svn.serv/Bla/Bla  directory/path/Local.git.Repo

“开始” 命令在此处是可选的(Windows)。它将看到启动时的错误,并在 SubGit 完成后保持打开外壳的状态。

您可以在此处添加类似于 git-svn 的其他参数 。我仅使用--default-domain myCompanyDomain.com来修复 SVN 作者的电子邮件地址的域。
我具有标准的 SVN 信息库的结构(主干 / 分支 / 标签),“作者映射” 没有问题。所以我什么也没做。

(如果要迁移分支等标记,或者您的 SVN 具有多个分支 / 标记文件夹,则可以考虑使用更详细的 SubGit 方法

提示 1 :使用 --minimal-revision YourSvnRevNumber 可以快速了解问题的解决方法(某种调试)。查看已解析的作者姓名或电子邮件特别有用。
或限制迁移历史深度。

提示 2 :迁移可能会中断( Ctrl + C ),并通过运行下一个更新命令 / 文件来恢复。
我不建议对大型存储库执行此操作。我收到 “内存不足 Java + Windows 异常”。

技巧 3 :最好为您的结果裸存储库创建一个副本。

用于更新的文件 / 命令的内容:

start    subgit import  directory/path/Local.git.Repo

要获取上一个团队对 Git 存储库的提交,可以运行任意次。

警告!不要触摸您的裸仓库(例如创建分支)。
您将遇到下一个致命错误:

无法恢复的错误:不同步,无法同步... 将 Subversion 修订翻译为 Git 提交...

3.运行第一个命令 / 文件。大型存储库将花费大量时间。我的不起眼的资料库需要 30 个小时。

就是这样
您可以随时通过运行第二个文件 / 命令从 SVN 更新 Git 存储库。在将您的开发团队转到 Git 之前。
只需几秒钟。



还有另一项有用的任务。

将本地 Git 存储库推送到远程 Git 存储库

是你的情况吗?让我们继续。

  1. 配置遥控器

跑:

$ git remote add origin url://your/repo.git
  1. 准备将庞大的本地 Git 存储库初始发送到远程存储库

默认情况下,您的 Git 无法发送大块数据。 致命:远端意外挂断

让我们开始吧:

git config --global http.postBuffer 1073741824

524288000-500 MB 1073741824-1 GB 等

解决本地证书问题 。如果您的 git-server 使用损坏的证书。

我已禁用证书

另外,您的 Git 服务器可能有一个请求量限制,需要更正

  1. 将所有迁移推送到团队的远程 Git 存储库。

使用本地 Git 运行:

git push origin --mirror

git push origin'*:*'对于旧的 Git 版本)

如果得到以下信息: 错误:无法生成 git:没有这样的文件或目录 ... 对我来说,完全重建我的存储库可以解决此错误(30 小时)。您可以尝试下一个命令

git push origin --all
git push origin --tags

或尝试重新安装 Git对我无用 )。或者,您可以根据所有标签创建分支并将其推送。或者,或者,或者...

后代

对于复杂的情况, Eric S. Raymond 的回骨术是首选工具。除了 SVN 之外,它还通过fast-export格式以及CVS支持许多其他版本控制系统。作者报告了EmacsFreeBSD等古代存储库的成功转换。

该工具显然旨在实现近乎完美的转换 (例如,将 SVN 的svn:ignore属性转换为.gitignore文件),甚至适用于历史悠久的困难存储库布局。在许多情况下,其他工具可能更易于使用。

在深入研究reposurgeon命令行的文档之前,请务必阅读出色的DVCS 迁移指南 ,该指南逐步介绍了转换过程。