首先,感谢@cmcginty的回答。对我来说,这是一个很好的起点,我在此基础上借鉴了很多。然而,我要移动的仓库有数年的历史,所以按照那个回答的方法会出现一些问题(例如需要手动移动数百个分支和标签,详情请见后文)。
经过数小时的搜索和试错,我成功编写了一个脚本,可以轻松地将多个项目从SVN迁移到GIT,并且我决定在这里分享我的发现,以防其他人也遇到同样的问题。
<tl;dr> 让我们开始吧
首先,创建一个“作者”文件,将基本的svn用户转换为更复杂的git用户。最简单的方法是使用命令从要移动的svn仓库中提取所有用户。
svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt
这将生成一个名为authors-transform.txt的文件,其中每个用户在运行它的svn仓库中所做的更改都会有一行记录。
someuser = someuser <someuser>
更新以包括Git的全名和电子邮件。
someuser = Some User <someuser@somewhere.com>
现在使用您的作者文件开始克隆。
git svn clone --stdlayout --no-metadata -r854:HEAD --authors-file=authors-transform.txt https://somesvnserver/somerepo/ temp
- --stdlayout指示svn仓库遵循标准的 /trunk /branches /tags 布局
- --no-metadata告诉git不要在每个git提交上盖章与svn提交相关的元数据。如果这不是单向转换,请删除此标记
- -r854:HEAD只获取从版本854开始的历史记录。这是我遇到的第一个障碍; 我要转换的仓库在853版本处有一个“损坏”的提交,因此无法克隆。使用此参数可以让您仅克隆部分历史记录。
- temp是将被创建以初始化新git仓库的目录名称
这一步可能需要一段时间,特别是对于大型或旧的仓库(我们其中一个大约需要18小时)。您还可以使用-r开关仅获取少量历史记录以查看克隆情况,并稍后获取其余部分。
移动到新目录
cd temp
如果你只克隆了部分内容,那么请获取任何缺失的历史记录。
git svn fetch
在克隆时,标签会被创建为分支。如果您只有几个标签,可以逐个进行转换。
git 1.0.0 origin/tags/1.0.0
然而,如果你有数百个标签,这将变得很繁琐,所以以下脚本对我很有用。
for brname in `git branch -r | grep tags | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do echo $brname; tname=${brname:5}; echo $tname; git tag $tname origin/tags/$tname; done
你还需要检出你想要保留的所有分支。
git checkout -b branchname origin/branches/branchname
如果您也有许多分支,那么这个脚本可能会有所帮助。
for brname in `git branch -r | grep -v master | grep -v HEAD | grep -v trunk | grep -v tags | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do echo $brname; git checkout -b $brname origin/$brname; done
这将忽略主干分支,因为它已经被检出为主分支,并在稍后删除重复分支时节省了一步,同时忽略我们已经转换的/标签。现在是检查新存储库并确保您拥有本地分支或标记以保留任何要保留的内容的好时机,因为远程分支将很快被删除。现在,让我们将所有已检出的内容克隆到一个干净的存储库(此处命名为temp2)。
cd ..
git clone temp temp2
cd temp2
现在,我们需要再次检出所有分支,然后将它们推送到最终的远程仓库,因此请按照上述方法中您喜欢的方法进行操作。
如果您正在遵循gitflow流程,您可以将工作分支重命名为develop。
git checkout -b WORKING
git branch -m develop
git push origin --delete WORKING
git push origin -u develop
现在,如果一切看起来都很不错,你就可以将其推送到你的git代码库。
git remote set-url origin https://somebitbucketserver/somerepo.git
git push -u origin --all
git push origin --tags
我遇到的最后一个问题是Control Freak最初阻止我推送我没有创建的标签,因此如果您的团队使用Control Freak,则可能需要禁用或调整该设置以进行初始推送。