SVN 迁移至 Git 完整记录

Git 万岁

为什么在 8102 年还在用 SVN 就不要问我了..总之 Git 万岁…

Clone

完整迁移

Git 提供了从 SVN 迁移的工具命令 git svn clone, 可在 SVN 中, 是以目录形式, trunk, branches, tags 来存储的, 如何保留呢?

如果你的 SVN 中都是以标准形式存储即 trunk 中为主干, branches 中为所有分支, 则可以直接使用参数 -s, 否则则需要自己指定对应的目录.

比如, 我们的项目中, 分支是以这种目录结构存储的

branches
  |
  |- develop
  |     |
  |     |- dev1_分支
  |     |- dev2_分支
  |
  |- personal
  |     |
  |     |- xxx1_分支
  |     |- xxx2_分支

则, 我需要使用多个 –branches 命令来指定对应的两个分支目录

--branches=branches/develop --branches=branches/personal

用来指定我们的两个分支目录 branches/developbranches/personal, 这里需要特别注意的是 指定的分支目录应该是分支所在文件夹的上一级文件夹, 比如此处目录是 branches/develop, 而不应该是 branches/develop/dev1_分支

在我们项目中, trunk 和 tags 都是按照标准形式存储的, 所以只要再加一个命令 -s 即可, 相当于补充了 --trunk=trunk --tags=tags --branches=branches 只不过我们这里 branches 里面没有分支了. 这个没关系~

所以 clone 的完整命令如下

git svn clone http://xxxx/xxxx/xxxx/xxxx \
    --branches=branches/develop \
    --branches=branches/personal \
    -s

用户信息

这样其实已经是没问题的了, 但是我们还希望在 SVN 上提交的用户信息也能顺利的迁移到 Git 中来, 因为 SVN 中提交信息只有用户名, 而 Git 则需要用户名和邮箱两个信息, 所以需要制定名称对应名称和邮箱的映射关系.

这里我使用文件的方式, 在本地创建好文件夹, 准备一会进行 clone, 在此文件夹中, 我创建了 name.txt 来进行名称的映射, 内容格式如下:

yuanxuhan = yuanxuhan <yuanxuhan@xxx.com>
xxx = xxx <xxx@xxx.com>

需要注意的是, 如果想要进行用户信息的迁移, 则需要把在 SVN 中提交过的所有用户信息都要进行对应, 否则会报错

然后在 clone 的命令中, 增加 --authors-file=name.txt 来指定映射信息文件

为了获得 SVN 使用的作者名字列表,可以运行这个:

svn log –xml | grep author | sort -u | \
perl -pe ‘s/.>(.?)<.*/$1 = /‘

完整命令

git svn clone http://xxxx/xxxx/xxxx/xxxx \
    --authors-file=users.txt \
    --branches=branches/develop \
    --branches=branches/personal \
    -s

等待 clone 完毕

整理

保留分支

clone 完毕之后, 使用 git branch, 发现只有一个 master 分支, 其实是 Git 将 SVN 的 trunk 转换成了 master, 而其他的 branches 则变成了 git 的 remote 分支 origin/xxx, 以远端分支的形式存在了本地, 可以使用命令 git branch -r 检查分支转换的没毛病~

这里我们要保留所有分支信息. 所以要对所有分支进行 checkout -b, 按照自己 Git 的一些规范保留分支即可. 如

git checkout -b feature/3.0.1 origin/dev1_分支

如果不需要整理分支名等需求, 也可以使用下面提供的直接移动文件夹的操作

保留 tag

我们这个项目比较小, 还没有 tag, 如果有的话可以参照文档提供的方法(未试过)

为了将标签变为合适的 Git 标签,运行

$ cp -Rf .git/refs/remotes/origin/tags/* .git/refs/tags/
$ rm -Rf .git/refs/remotes/origin/tags

这会使原来在 remotes/origin/tags/ 里的远程分支引用变成真正的(轻量)标签。

接下来,将 refs/remotes 下剩余的引用移动为本地分支:

$ cp -Rf .git/refs/remotes/* .git/refs/heads/
$ rm -Rf .git/refs/remotes

删除远端信息

将所有分支都整理完毕后, 使用 git branch 检查确认无误之后, 删除 origin 的信息即可,

git remote rm origin

或者

rm -Rf .git/refs/remotes

配置

钩子

整理之后可以进行配置 Git hook 等等其他信息, 这个使用的是我们小组的规范脚本, 不方便记录.

.gitignore

https://www.gitignore.io

可以在这个网址 输入三个关键字, Swift, Xcode, macOS 会自动组合好 .gitignore 文件, 存放到 Git 仓库目录中并提交.

新增 tag

之前 SVN 管理的比较松散, 转换之后, 应该在 App Connet 中, 找到上架包的版本号和 build 号, 在持续集成平台中查找该版本的对应 build, 查看最后一个 commit, 并在该 commit 处增加 tag, 并且分支可以删掉了, 以便线上 bug 的定位和解决.

关联远端

在 Git 服务器创建好新的仓库后, 关联一下远端服务器

git remote add origin http://xxx/xxx.git

推送所有分支

git push origin --all

推送所有标签

git push origin --tags

Reference

9.2 Git 与其他系统 - 迁移到 Git