前言

进行代码仓库的迁移并非简单地创建 Git repo 把当前项目代码一次性 commit 过去就够了,因为 SVN 中存有长年累月的 commit 历史记录,丢失历史记录将对今后追溯 debug 造成非常大的麻烦,所以如何保留 commit 记录就是迁移的关键。

迁移步骤

创建用户映射 (例如 users.txt) ,将 SVN 用户和 Git 用户对应起来:

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

如果上面的文件中有用户缺失,后面的 SVN 命令将会停止。不过你可以更新用户映射然后接着再来(类似断点续传)。

现在从 SVN 仓库中拉取所有数据:

1
git svn clone --stdlayout --no-metadata -A users.txt svn://hostname/path dest_dir-tmp

这个命令将会在 dest_dir-tmp 新建一个 Git repo,并开始从 SVN 中拉取代码。请注意 “--stdlayout” 参数表示你的项目在 SVN 中是常见的 “trunk/branches/tags” 目录结构,如果不是,那你需要使用 --tags, --branches, --trunk 参数(请通过 git svn help 自行了解)。

再后面的参数是 SVN 的地址,一些常见协议都是支持的 : svn://, http://, https://。 注意这个 URL 应该指向项目的 base repository,例如 http://svn.mycompany.com/myrepo/repository. 不要指到了 /trunk, /tag/branches 里。

如果出现用户名没找到,更新你的 users.txt 文件,然后

1
2
cd dest_dir-tmp
git svn fetch

如果你的项目非常大,你可能需要重复上面的命令好几次,直到所有的 SVN commit 都被抓下来了:

1
git svn fetch

完成后,Git 将会 checkout SVN 的 trunk 到一个新的 Git branch,而其他的 SVN branch 将会设为 Git remote,你可以查看所有的 SVN branch:

1
git branch -r

如果你想在你的 Git repo 中保留其他的 remote branch,你需要手动创建本地 branch。否则,SVN 的 branch 将不会在最后被 clone。

1
2
3
4
5
6
7
8
git checkout -b local_branch remote_branch
# it's ok if local_branch and remote_branch are the same name
SVN tags 被当作 branch 导入了,你需要创建本地 branch,打一个 tag,然后删掉那个 branch,这样才会在 Git 中生成 tag。例如 SVN tag “v1”:

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

把上面的 GIT-SVN repo Clone 到一个全新的干净 git repo:

1
2
3
git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir

之前从 remote branch 创建的本地 branch 又会在新 clone 的 repo 中成为 remote branch,于是对每个 branch 再做一次:

1
git checkout -b local_branch origin/remote_branch

最后,从干净的 Git repo 中删掉 remote (指向我们刚刚已经删掉的 temp repo)

1
git remote rm origin

这样一个全新 Git repo 就已经从 SVN 迁移好了。

完整的命令行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
##clone svn -> git 地址支持协议 : svn://, http://, https://. 注意这个 URL 应该指向项目的 base repository,例如 ##http://svn.mycompany.com/myrepo/repository. 不要指到了 /trunk, /tag 或 /branches 里。
git svn clone svn://10.68.245.11/tclshop --authors-file=users.txt --no-metadata -s dufy-move
##进入clone 的文件夹
cd dfuy-move
##使所有的 SVN commit 都被抓下来了
git svn fetch
##在git中查看svn commit记录信息
git log --pretty=oneline
##查看分支 -- svn tag的被解析为git分支 ,需转换一下
git branch -r
##转换分支-tag
git tag tags_20160329_hg origin/tags/tags_20160329_hg
##删除远程的分支(tags)
git branch -r -d origin/tags/tags_20160329_hg
##本地初始化git仓库完成
git remote add origin git@10.68.25.20:move/dufy-tclshop-test-two.git
#推送到远端的git的仓库中
git push origin master --tags
##切换到分支
git checkout 16130_20151125_hg
##提交分支到远程的仓库中
git push origin 16130_20151125_hg