全部产品

SVN 如何迁移至 Git

SVN (Subversion) 是一个曾经热门的集中式版本控制工具,然而 Git 作为分布式版本控制工具,近年来越来越受欢迎,很多公司、开发人员开始使用 Git 来替代 SVN。

针对历史代码迁移的问题,最原始而直接的方法是把代码手动下载下来,然后手动创建 Git 仓库,再把代码 Push 上去,但是这样做会造成原 SVN 中的 Commit 纪录丢失。

如何在保留历史记录的情况下,让代码资产从 SVN 顺利的迁移至 Git 呢?本文基于git-svn查看更多)为基础进行讲解。

建立 SVN 用户到 Git 用户的映射

在 SVN,每个提交者在主机上有一个用户名,记录于提交信息中,而 Git 使用作者名称和邮箱来标记用户。

如果想迁移前后保证 Commit 作者信息可追溯,需要建立从 SVN 用户到 Git 作者的映射关系,这需要建立一个叫做 userinfo.txt 的文件,利用 SVN 作者 = 作者昵称 <邮箱地址>的格式表示映射关系。

查看 SVN 用户

首先检出全部 SVN 用户列表:

svn log --xml | grep "^<author" | sort -u | \awk -F '<author>' '{print $2}' | awk -F '</author>' '{print $1}' > userinfo.txt

输出的 userinfo.txt 文件内容如下:

alex
misha
loki

描述映射关系

接着按以上格式描述映射关系:

alex = alex <alex@alibaba.com>
misha = misha <misha@alibaba.com>
loki = loki <loki@alibaba.com>

此时,userinfo.txt 就准备好了,接下来开始克隆 SVN 地址。

下载 SVN 代码库

操作之前,你需要了解 SVN 目录和 Git 的关系:

SVN目录

  • /trunk:开发主线,相当于 Git 中的 Master 分支;

  • /branches:支线副本,相当于 Git 中的其余分支;

  • /tags:标签,与 Git中 的标签一样;

下载 SVN 仓库

把上一步准备好的 userinfo.txt 拷贝到准备克隆 SVN 代码的目录下,然后执行git svn clone命令克隆一个 Git 版本库。

如果你的项目是完全按照 trunk,branches,tags 来管理的,只需使用--stdlayout进行范围指定,迁移的命令可以写作如下:

git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --authors-file=userinfo.txt --stdlayout 

如果是非标准格式的仓库,可以通过 --trunk,--branches 和 --tags 去指定:

git svn clone ["SVN repo URL"] --prefix=svn/ --no-metadata --authors-file=userinfo.txt --trunk=trunk --tags=tags --branches=branches
  • 参数 –no-metadata 表示阻止 Git 导出 SVN 包含的一些无用信息;

  • 参数 –authors-file 表示 SVN 用户映射到 Git 用户的说明文件;

  • 参数 –trunk 表示指定 SVN 的 trunk 分支;

  • 参数 –branches 表示指定 SVN 的支线分支;

  • 参数 –tags 表示指定 SVN 的标签;

ignore 文件转换

如果 SVN 库使用 svn:ignore 属性,可以使用以下命令将其转换为 .gitignore 文件:

cd [下载后目录]
git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

“ trunk”分支重命名为“ master”

转换后,您的主要开发分支将被命名为“ trunk”,即 SVN 中的开发分支。

可以使用以下命令将其重命名为 Git 标准的“ master”分支:

git branch -m trunk master

清理标签

git-svn使所有 SVN 标签变成了 Git 中非常短的分支,形式为“标签/名称”,因此需要将这些短分支转换为实际的 Git 标签或删除掉它们,转换为 Git 标签的命令如下:

git for-each-ref --format='%(refname)' refs/heads/tags | % { $_.Replace('refs/heads/tags/','') } | % { git tag $_ "refs/heads/tags/$_"; git branch -D "tags/$_" }

转换其他分支为本地 Git 分支

除了标签转换外,还可以把远端剩下的分支变成本地 Git 分支:

git for-each-ref --format='%(refname)' refs/remotes | % { $_.Replace('refs/remotes/','') } | % { git branch "$_" "refs/remotes/$_"; git branch -r -d "$_"; }

推送至 Git 服务器

VN 代码已经 clone 到本地了,接着需要 push 到 Codeup 的服务端。

创建一个空仓库

参见 创建第一个代码库

接着在下图①处获取 Git 库地址:

空仓库

接下来就可以将本地的仓库 push 到远程地址,命令如下:

git remote add origin git@codeup.xxxx.git

推送至远端 Git 仓库

git push origin --all

如果原来的 SVN 项目有 Tags 的话, git push -u origin –all 运行之后并不能让分支和标签都推送到远端。实际上,只提交了 branches ,并没有提交tags。此时,你需要执行一下git push –tags

git push -u origin --tags

使用 Git 仓库

更多使用说明参见快速上手

附录

Git 迁移相关材料参见:https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git