本文首次更新地址:https://www.veaxen.com/svn迁移到git仓库并保留commit历史记录.html
csdn博客作为备份保留,更多内容请访问https:www.veaxen.com
环境准备
sudo apt-get install subversion
sudo apt-get install git
sudo apt-get install git-svn
迁移
首先用svn将代码checkout到本地
svn checkout http://svn.company.com/projectname
创建用户映射
在subversion,每个提交者都在主机上有一个用户名,记录在提交信息中,比如blame的输出以及git svn log。如果想要让这条信息过呢更好的映射到git里面,需要在svn用户名到git用户名之间建一个映射关系,我们这里用user.txt文件来建立这个映射关系:
veaxen = veaxen <veaxen@veaxen.com>
jack = jack <jack@veaxen.com>
tom = tom <tom@veaxen.com>
在svn库下执行下面的命令生成user.txt,获取svn作者的列表:
svn log --xml | grep -P "^<author" | sort -u | perl -pe 's/<author>(.*?)<\/author>/$1 = /' > user.txt
根据svn账号与git账号的映射,补充user.txt为上述格式。
导出svn工程
利用git clone ...
命令,可以将svn工程导出为git工程,但是如果只是简单的执行下面命令的话:
svn checkout http://svn.company.com/projectname/trunk
那么我们只是将其中的主分(trunk分支)支及其log拉去到本地,其他分支并没有,需要用到--trunk
、--tags
、--branches
等选项。
需要注意的有下面几点:
- 除了
trunk
单词是单数之外,其他选项单词都是复数。--trunk
参数指明了svn主分支所在目录,如果不指明默认是trunk目录,--tags
指明了svn的tag所在目录(我们公司没有用到tag管理代码,这里我忽略),--branches
参数指明了其他分支所在目录,如果不指明默认是branches目录。 - 这几个选项指定的都是相对路径,相对于
git svn clone
后面紧跟着的路径位置,所以不要在选项里制定诸如“http://”开头的相对路径。 - 除了trunk之外,其他几个选项都可以重复指定,如果你的分支/标签分别在svn目录上的不同文件夹下,可以多次指定。
于是,对应我的实际情况,git-svn命令是这样的:
git svn clone http://svn.company.com/projectname/ \ #注意这里写到项目根目录,而不是写到分支所在路径
--trunk="trunk" --branches="branch" \ #这里的trunk可以不指定,而branches则是一定要指定的,这是由于我们的svn项目的目录不是标准的svn目录,我们的其他分支是在branch目录下,而不是svn建议的branches目录
--no-metadata --authors-files=user.txt \ #前一个参数用来阻止git svn包含哪些svn附带的信息,后一个参数是根据文件里指定的映射关系,将svn用户同git用户联系起来
projectname
稍等一会,就可以看到真个svn的主分支和其他分支都被导出来了,并且保留了commit信息,一棵赛艇!??
分支处理
执行git branch -a
可以看到相应的分支已经按照我们指定的选项建立起来了,我的实际情况是:
git branch -a
* master
remotes/origin/develop
remotes/origin/func_01_branch
remotes/origin/func_02_branch
remotes/origin/func_03_branch
remotes/origin/func_04_branch
remotes/origin/func_05_branch
remotes/origin/trunk
你会发现,remotes/origin/xxx这样的分支,git会认为他们是虚拟的远程分支,我们可以通过下面命令将分支拉到本地(以develop为例):
git checkout -b develop remotes/origin/develop
还有一点要说明的是,remotes/origin/trunk分支其实与本地master分支是一样的,所以我们没有必要将这个分支转换为本地分支。
上传到git服务器
首先要在git服务器上创建一个空的工程,比如“git@rdgit.company.com/some_group/projectname.git”
然后再本地仓库执行:
git remote add origin git@rdgit.company.com/some_group/projectname.git
将主分支上传到git服务器:
git push origin master:master
其他分支也是利用这个语句创建新分支上传。
完成之后,在git服务器上就可以看到完整的change log以及分支的变化情况了。
关于空目录
其实迁移的时候还需要注意一个问题,那就是 svn 支持空目录的版本控制,但是 git 不支持。
导出 svn 之后,最好对比一下原始的 svn 工程内是否有空目录。如果有,那么你需要手工(或者写脚本)在导出的 git 工程中创建这些目录,并且在目录中建立一个 “.gitkeep” 文件(这是约定俗成的做法),并且将这些文件git add .gitkeep
,以加入 git 的版本控制。这样就以迂回的方式通过 git 版本控制了目录。