如何把 SVN 仓库迁移到 Git 并保留历史
SVN 迁移 Git 用 git svn clone:准备作者映射文件(users.txt),git svn clone --stdlayout --authors-file 完整转换历史、分支、标签,再清理引用推到 Git 远程。大仓库建议通宵跑。
官方工具 git svn clone 可迁移 SVN 提交及配置范围内的分支/标签历史,但不保证所有合并关系、属性和已删除路径都完整转换。 关键准备是作者映射文件——SVN 用户名要映射成 Git 的"名字 <邮箱>"格式。
迁移步骤
# 1. 生成作者映射(从 SVN 日志提取所有提交者)
svn log --xml https://svn.company.com/repo > svn-log.xml
# 从 XML author 字段整理、去重并人工核对 users.txt,例如:
# alice = Alice Zhang <alice@company.com>
# 2. 克隆转换(trunk/branches/tags 标准布局)
git svn clone https://svn.company.com/repo --stdlayout --prefix=svn/ --authors-file=users.txt my-repo
cd my-repo
--stdlayout 对应标准的 trunk/branches/tags 结构;非标准布局用 -T/-b/-t 单独指定。
转换后的清理
# 先列出并核对引用,避免把提交哈希/类型误当分支名
git for-each-ref --format='%(refname)' refs/remotes/svn/
# 根据实际清单逐项转换,以下仅为名称示例:
git branch feature-x refs/remotes/svn/feature-x
git tag v1.0 refs/remotes/svn/tags/v1.0
# 推到新远程
git remote add origin git@github.com:org/repo.git
git push --all && git push --tags
注意事项
- 大仓库转换可能跑数小时,建议服务器上执行;
- SVN 的 svn:ignore 转成 .gitignore(
git svn show-ignore); - 切换前冻结 SVN 写入,完成最后一次 git svn fetch 并核对差异,再创建最终引用和推送;保留 git-svn 元数据以支持过渡期增量同步。
常见问题(FAQ)
Q:迁移后还能回 SVN 吗?
git svn 支持双向(dcommit 回推 SVN),但过渡期越长同步成本越高。建议一刀切,SVN 归档只读。
Q:SVN 的目录拷贝式分支在 Git 里什么样?
git svn 会尽量识别为真正的分支。SVN mergeinfo 不会自动成为等价 Git merge 祖先;SVN 标签可修改,Git 标签则指向固定提交。需核对删除过的分支、属性、externals 和目标目录范围,不能把转换成功视为完整保真。
Q:有没有更现代的工具?
reposurgeon、svn2git(基于 git svn 的封装,处理分支标签更自动化)。数据量大或布局怪异时值得试。