SVN 项目移植 Git

由于公司 SVN 服务不再维护,同时我没有项目的 SVN 管理权限,需将当前项目移植至 Git 上。
这类需求应该很普遍,Google 之,果然发现一条靠谱的答案:https://stackoverflow.com/a/3972103。
这里简单翻译下这篇文,加上本人的实践操作,做些笔记备忘

提取人员信息

svn log -q                                                                               \
    | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' \
    | sort -u > users.txt

拉取 SVN 记录

如果你的 SVN 仓库是标准结构(trunk/,branches/,tags/),

git svn clone                \
    --stdlayout              \
    --no-metadata            \
    --authors-file=users.txt \
    https://hostname/path    \
    dest_dir-tmp/

否则需要另加参数(详细请看 git svn help),

git svn clone --no-metadata  \
    --tags=tag               \
    --branches=branch        \
    --trunk=baseline         \
    --authors-file=users.txt \
    https://hostname/path    \
    dest_dir-tmp/

PS: 如果去掉 --no-metadata 参数,Git 会把相应的 SVN revision 加入提交信息中。
(git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>)

拉取过程可能比较漫长,需要耐心等待……

如果因为在 users.txt 中找不到相应用户而导致 SVN 停止,可以自己手动更新 users.txt,然后继续。

# In dest_dir-tmp
git svn fetch

分支、Tag 处理

完成后,Git 将 SVN 「trunk」检出作为新分支,而其他分支设置为远程分支。
可以通过以下命令查看:

git branch -r

检出分支

如果你想保存其他远程分支,你需要自己手动创建本地分支(排除 trunk/master)。
否则,最后一步无法 clone 到这些分支。

git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same name

检出 Tag

Tag 被当作分支导入。你需要创建一个本地分支,打 tag 然后删除该本地分支。

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

懒 style

上面的操作一个个操作下来要爆炸,所以自己弄了点 shell 脚本。
执行相应脚本,只会打印相应操作。确保操作正确后,去掉脚本中的 echo 即可实际执行脚本。
另外,这里用的是 GNU 的 awk 和 sed

# 检出所有远程分支,根据情况自己修改
git branch -rvv                       \
    | awk -e '{print $1}'             \
    | sed -ne 'h;s!^origin/!!;p;g;p;' \
    | xargs -n2 echo git checkout -b
# 执行上面脚本后,才能执行此脚本
# 给带 tag 的本地分支打标签,根据情况自己修改
git checkout master
git branch                            \
    | grep tags                       \
    | awk -e '{print $1}'             \
    | sed -ne 'h;s!^tags/!v!;p;g;p;' \
    | xargs -n2 echo git tag

# 删除 tag 分支
git branch | grep tags | xargs git branch -D

干净的 Git 仓库

git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir

前一步创建的本地分支在这里又变为远程分支,需要再来一遍(可以参考上一步骤):

git checkout -b local_branch origin/remote_branch

最后清除 remote,

git remote rm origin