SVN项目迁移Git

SVN项目迁移Git

Scroll Down

公司不同项目组用的版本管理工具也不一样,今天把公司的某个svn项目迁移到git,记录一下操作流程,以便不时之需。

参考链接

准备工作

如下操作是为了将svn的作者信息迁移至git

  1. 进入SVN项目的目录内,右击选择Git Bash Here
  2. 使用如下命令获取所有作者名
svn log --xml | grep -P "^<author" | sort -u | perl -pe 's/<author>(.*?)<\/author>/$1 = $1 <$1\@email.com>/' >> userinfo.txt

在SVN中,每个提交者在主机上有一个用户名,记录在提交信息中。如果想让已有的信息更好的映射到 Git 作者数据里,则需要 从SVN用户名到Git作者的一个映射关系,因为Git是用邮箱来标识一个提交者的。建立一个叫做 userinfo.txt 的文件,每行一条svn作者 = 作者昵称 <邮箱地址>

  1. 执行完后会在当前目录输出一个txt文本userinfo.txt,打开后会看到类似如下的内容:
chenwenxiang = chenwenxiang <chenwenxiang@email.com>
jiaweiguang = jiaweiguang <jiaweiguang@email.com>
zhaoguorun = zhaoguorun <zhaoguorun@email.com>
  1. 请将邮箱替换成真实的邮箱,如果不知道可以选择不改

将svn仓库迁移至git

将userinfo.txt文件copy至要迁移的git目录

例如:
我的userinfo.txt 在d:/work/svn/tmd/userinfo.txt
则将userinfo.txt copy至 d:/work/git/userinfo.txt

  1. 打开Git Bash Here 执行如下命令
git svn clone https://21x.14x.x9x.x7x:18080/svn/tdm/ --no-metadata --authors-file=userinfo.txt --trunk=trunk --tags=tags --branches=branches
参数–no-metadata表示阻止git导出SVN包含的一些无用信息
参数–authors-file表示SVN账号映射到git账号文件,所有svn作者都要做映射
参数–trunk表示主开发项目,相当于git中的master
参数–branches表示分支项目,同git中的branch
  1. 执行后会弹出OpenSSH 要求你输入svn的用户名和密码,输入回车之后会进入一段长时间的等待执行过程,执行过程就是git从svn服务器上拉取代码到本地

  2. 拉取成功后可以使用 git log 查看历史提交记录,如果不存在,可以关掉 Git Bash Here 重新打开 然后再执行 git log

修复“不存在”的分支

  1. 使用 git branch 查看分支,会看到只有master分支,不要紧看如下操作
  2. 使用 git show-ref 查看所有引用
refs/heads/master
refs/remotes/origin/master
refs/remotes/origin/origin/branch_rebuild_201905
refs/remotes/origin/origin/trunk
refs/remotes/origin/origin/uploadOriginalDataByBatches

可以看到本地分支只有 master

将远程分支添加到本地分支

  1. 方法一 首先要移动标签,把它们从远程分支变成实际的标签,然后把剩下的分支移动到本地。要把标签变成合适的Git标签,运行
cp -rf .git/refs/remotes/tags/* .git/refs/tags/
rm -rf .git/refs/remotes/tags

该命令将原本以tag/开头的远程标签索引变成真正的本地标签。
接下来,把refs/remotes下面的远程分支索引变成本地分支:

cp -rf .git/refs/remotes/* .git/refs/heads/
rm -rf .git/refs/remotes

合起来就是共执行以下命令

cp -rf .git/refs/remotes/tags/* .git/refs/tags/
rm -rf .git/refs/remotes/tags

cp -rf .git/refs/remotes/* .git/refs/heads/
rm -rf .git/refs/remotes

执行如上操作时,出现git/refs/remotes/tags/目录不存在,且目录 .git/refs/remotes/origin/tags/ 存在时,请看 方法二

  1. 方法二
    当出现目录不存在报错后请执行如下命令
cp -rf .git/refs/remotes/origin/tags/* .git/refs/tags/
rm -rf .git/refs/remotes/origin/tags

cp -rf .git/refs/remotes/origin/* .git/refs/heads/
rm -rf .git/refs/remotes

执行成功后,所有的remote分支都变为本地分支,所有的远程标签也变成本地标签。

* master
  branch_rebuild_201905
  trunk
  uploadOriginalDataByBatches

如果提示 .git/refs/remotes/origin/tags/* 目录不存在 请看 方法三

  1. 方法三
    使用如下操作:
    首先要移动标签,把它们从远程分支变成实际的标签,然后把剩下的分支移动到本地。要把远程标签变成本地的Git标签,运行
git for-each-ref refs/remotes/tags | cut -d / -f 4- | grep -v @ | while read tagname; do git tag "$tagname" "tags/$tagname"; git branch -r -d "tags/$tagname"; done

上述命令将原本以 tag/ 开头的远程分支的索引变成本地标签。

接下来,把 refs/remotes 下面剩下的分支变成本地分支:

$ git for-each-ref refs/remotes | cut -d / -f 3- | grep -v @ | while read branchname; do git branch "$branchname" "refs/remotes/$branchname"; git branch -r -d "$branchname"; done

push到远程仓库

  1. 添加远程地址,执行
git remote add origin https://git.xxx.com/mikasa/tmd.git
  1. push到远程仓库
    执行 git push origin --all

  2. 如果您的项目中存在标签tags 则需要将标签push到远程去,执行
    git push -u origin –tags

  3. 查看远程仓库的web页面,是否项目分支、标签以及提交记录都存在。

例如 gitee、github、gogs、gitlab

同步SVN后续提交的代码

  1. 使用 git branch 查看远程分支
* master
  branch_rebuild_201905
  trunk
  uploadOriginalDataByBatches

trunk分支就是对应 git svn clone 生成的远程分支refs/remotes/origin/trunk

切换分支 git checkout trunk

  1. 如果不存在 trunk,使用 git show-ref查看远程分支名称,
refs/heads/master
refs/heads/branch_rebuild_201905
refs/heads/trunk
refs/heads/uploadOriginalDataByBatches
refs/remotes/origin/master
refs/remotes/origin/branch_rebuild_201905
refs/remotes/origin/trunk
refs/remotes/origin/uploadOriginalDataByBatches

remotes/origin/trunk就是git svn clone 生成的远程分支,创建本地分支,使用命令 git checkout -b trunk remotes/origin/trunk ,创建并切换到trunk分支。

  1. 使用git svn fetch命令同步SVN最新的提交记录,然后可以通过 git log 命令查看git的提交记录对应的SVN记录相同。

  2. 切换到master分支,然后merge刚才的trunk分支

git checkout master   	# 切换到主分支
git merge trunk		# 合并
  1. 使用 git push push到远程分支