svn2git vs git-svn
svn2git:一次性完整迁移,适合永久迁移到 Git
git-svn:双向同步工具,适合过渡期或需要继续使用 SVN
📋 功能对比表
| 特性 |
svn2git |
git-svn |
| 用途 |
一次性迁移 |
双向桥接 |
| 分支处理 |
✅ 自动转换为 Git 分支 |
❌ 保持为远程分支 |
| 标签处理 |
✅ 自动转换为 Git 标签 |
❌ 保持为远程分支 |
| 作者映射 |
✅ 支持 |
✅ 支持 |
| 增量迁移 |
❌ 不支持 |
✅ 支持 |
| 双向同步 |
❌ 不支持 |
✅ 支持 |
| 学习曲线 |
简单 |
较复杂 |
| 适合场景 |
永久迁移 |
过渡期/并行使用 |
svn2git
准备环境
# 1. 安装必要工具
sudo dnf install git subversion ruby ruby-devel gcc make
# 2. 安装 svn2git
sudo gem install svn2git
# 3. 创建工作目录
mkdir ~/svn-migration && cd ~/svn-migration
获取SVN信息
# 查看 SVN 仓库结构
svn list svn://svn-server/
# 应该显示所有仓库列表,如:project1/ project2/
# 查看具体仓库结构
svn list svn://svn-server/project1
# 应该看到:trunk/ branches/ tags/ 或类似结构
# 获取作者列表
svn log --xml svn://svn-server/project1 | \
grep author | \
sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = $1 <$1@xxxx-it.cn>/' > authors-project1.txt
创建作者映射文件
# 编辑 authors.txt
cat > authors.txt << 'EOF'
lx = 李兴 <lixing@xxxx-it.cn>
zhangsan = 张三 <zhangsan@xxxx-it.cn>
admin = 管理员 <admin@xxxx-it.cn>
(no author) = 未知用户 <unknown@xxxx-it.cn>
EOF
创建项目特定的作者映射
# 获取该项目的历史作者
svn log --xml svn://192.168.1.100/svn/project-a | \
grep author | \
sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = $1 <$1@xxxx-it.cn>/' > authors-project-a.txt
执行迁移
# 使用 svn2git 迁移
svn2git svn://192.168.1.100/svn/project1 \
--trunk trunk \
--branches branches \
--tags tags \
--authors authors.txt \
--verbose 2>&1 | tee migration.log
# 分批次迁移
svn2git svn://server/repo \
--revision 0:500 \
--authors authors.txt
# 然后继续
svn2git --revision 501:1000
验证迁移结果
# 进入迁移后的目录
cd project1
# 查看 Git 仓库
git log --oneline | head -10
git branch -a
git tag -l
# 与 SVN 对比
svn log --quiet svn://192.168.1.100/svn/project1 | wc -l
git log --oneline | wc -l
推送到git
# 添加 Gitea 远程仓库
git remote add origin http://gitea.xxxx-it.cn/username/project1.git
# 推送所有分支
git push --all origin
# 推送所有标签
git push --tags origin
参数详解(完整列表)
基本参数:
| 参数 |
作用 |
示例 |
--trunk <path> |
指定主干路径 |
--trunk trunk |
--branches <path> |
指定分支路径 |
--branches branches |
--tags <path> |
指定标签路径 |
--tags tags |
--authors <file> |
作者映射文件 |
--authors authors.txt |
--verbose |
详细输出 |
--verbose |
--revision <start:end> |
迁移指定版本范围 |
--revision 100:500 |
高级参数:
| 参数 |
作用 |
示例 |
--username <name> |
SVN 用户名 |
--username lixin |
--password <pass> |
SVN 密码 |
--password Pass123 |
--metadata |
包含 SVN 元数据 |
--metadata |
--exclude <path> |
排除特定路径 |
--exclude branches/old |
--preserve-properties |
保留 SVN 属性 |
--preserve-properties |
布局参数:
| 参数 |
作用 |
使用场景 |
--notrunk |
无主干目录 |
非标准布局 |
--nobranches |
无分支目录 |
只有主干 |
--notags |
无标签目录 |
只有主干和分支 |
实际执行示例
标准 SVN 仓库迁移
# 假设 SVN 结构:
# svn://192.168.1.100/svn/project1/
# ├── trunk/
# ├── branches/
# └── tags/
svn2git svn://192.168.1.100/svn/project1 \
--trunk trunk \
--branches branches \
--tags tags \
--authors ./authors.txt \
--verbose
非标准布局
# 假设 SVN 结构:
# svn://192.168.1.100/project2/
# ├── main/ # 主干
# ├── features/ # 功能分支
# └── releases/ # 发布标签
svn2git svn://192.168.1.100/project2 \
--trunk main \
--branches features \
--tags releases \
--authors ./authors.txt
只有主干,无分支标签
# 假设 SVN 只有主干:
# svn://192.168.1.100/project3/
# └── src/ # 代码都在这里
svn2git svn://192.168.1.100/project3 \
--trunk src \
--nobranches \
--notags \
--authors ./authors.txt
主干就是根目录
# 非标准布局(无 trunk)
svn2git svn://server/project \
--rootistrunk
# 等价于:
svn2git svn://server/project \
--trunk . \ # 主干就是根目录
--nobranches \ # 没有分支目录
--notags # 没有标签目录
git-svn
自动执行
# 一行命令搞定所有
git svn clone svn://192.168.1.100/svn/project1 \
--stdlayout \
--authors-file=authors.txt \
--username lixing
# 完成!可以直接开始工作
cd project1
git log --oneline
# 只能处理标准参数
git svn clone svn://server/repo \
-T trunk -b branches -t tags
手动执行
初始化Git仓库
git init
配置
git svn init svn://192.168.1.100/svn/project1 \
--stdlayout \
--authors-file=authors.txt
--stdlayout:用于标准 SVN 布局,简化配置
--authors-file:用于美化提交历史,专业规范
获取数据
git svn fetch --username lixin -r 1:500
# 网络中断了?可以继续:
git svn fetch -r 501:HEAD
优化Git仓库
移除SVN相关信息:
在转换过程中,git-svn会在Git仓库中保留一些SVN的元数据。可以使用以下命令移除这些信息:
git config --remove-section svn
压缩Git仓库:
为了减少Git仓库的大小,可以使用以下命令压缩仓库:
git gc --aggressive --prune=now
验证和提交
- 检查转换结果:
使用以下命令检查Git仓库的历史记录,确保所有的SVN提交都正确转换为Git提交:
git log
- 添加远程仓库:
如果需要将本地Git仓库推送到远程Git仓库,可以使用以下命令添加远程仓库:
git remote add origin <远程Git仓库的URL>
- 推送到远程仓库:
将本地的Git仓库推送到远程仓库:
git push -u origin master