首先,归功于@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 repo 遵循标准 /trunk /branches /tags 布局
- --no-metadata 告诉 git 不要在每个 git 提交上标记与 svn 提交相关的元数据。如果这不是单向转换,请删除此标签
- -r854:HEAD 仅获取修订版 854 以上的历史记录。这是我遇到的第一个障碍;我正在转换的 repo 在修订版 853 中有一个“损坏的”提交,因此它不会克隆。使用此参数允许您仅克隆部分历史记录。
- temp 是为初始化新的 git 存储库而创建的目录的名称
此步骤可能需要一段时间,尤其是在大型或旧的 repo 上(我们的一个大约需要 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
这将忽略主干分支,因为它已经作为主分支检出,并在稍后删除重复分支保存步骤,并忽略我们已经转换的 /tags。
现在是查看新存储库的好时机,并确保您有一个本地分支或标签来存放您想要保留的任何内容,因为稍后将删除远程分支。
好的,现在让我们将我们签出的所有内容克隆到一个干净的 repo(这里命名为 temp2)
cd ..
git clone temp temp2
cd temp2
现在我们需要再次检查所有分支,然后再将它们推送到它们的最终远程,因此请从上面按照您最喜欢的方法进行操作。
如果您正在关注 gitflow,您可以将您的工作分支重命名为开发。
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,您可能需要禁用或调整该设置以进行初始推送。