如何将自定义结构的多模块SVN仓库迁移至Git并保留历史与标签?
绝对可以做到!我之前处理过类似的多模块SVN迁移场景,下面是一步步的实操方案,既能完整保留历史记录,又能生成符合你需求的Git标签:
准备工作
首先得先处理SVN用户到Git用户的映射,避免Git提交记录里出现陌生的SVN用户名:
- 导出SVN仓库的所有用户:
svn log --xml | grep -P "^<author" | sort -u | sed -e "s/<author>//" -e "s/<\/author>//" > authors.txt - 编辑
authors.txt,把每行改成Git用户格式:svn_username = Your Git Name <your.email@example.com>
克隆SVN Trunk到Git仓库
我们先把主分支的完整历史克隆到Git,对应SVN里的trunk/project/目录:
git svn clone --authors-file=authors.txt http://your-svn-repo-url/trunk/project/ my-git-repo cd my-git-repo
现在你的Git仓库根目录就是moduleX/、moduleY/、moduleZ/,和SVN trunk里的结构完全一致。
导入模块标签
因为你的SVN标签是每个模块单独复制的(而非整个project),我们需要手动关联这些标签到Git对应的提交:
添加SVN Tags远程仓库
编辑.git/config文件,添加以下配置(替换成你的SVN仓库地址):[svn-remote "svn-tags"] url = http://your-svn-repo-url/tags fetch = :refs/remotes/svn-tags/*然后拉取所有标签目录:
git svn fetch svn-tags手动创建单个标签
以moduleX-1.0为例:- 先找到这个标签在SVN中复制的源版本:
输出里会看到类似svn log -v --stop-on-copy http://your-svn-repo-url/tags/moduleX-1.0A /tags/moduleX-1.0 (from /trunk/project/moduleX:120)的行,这里的120就是SVN trunk中moduleX被复制时的修订版本号。 - 找到该SVN修订版对应的Git提交哈希:
git svn find-rev r120 - 创建Git标签:
git tag -a moduleX-1.0 <git-commit-hash> -m "Tag moduleX 1.0 release"
- 先找到这个标签在SVN中复制的源版本:
自动化处理所有标签(可选)
如果你的标签数量很多,手动处理太麻烦,可以用这个bash脚本批量生成标签:
#!/bin/bash SVN_URL="http://your-svn-repo-url" # 获取所有标签目录 TAGS=$(svn ls $SVN_URL/tags/) for TAG in $TAGS; do TAG_NAME=$(echo $TAG | sed 's/\/$//') # 提取复制源的SVN修订版本 COPY_INFO=$(svn log -v --stop-on-copy $SVN_URL/tags/$TAG | grep "from /trunk/project/") REV=$(echo $COPY_INFO | sed 's/.*:\([0-9]*\)).*/\1/') # 找到对应的Git提交 GIT_COMMIT=$(git svn find-rev r$REV) # 创建标签 git tag -a $TAG_NAME $GIT_COMMIT -m "Tag $TAG_NAME" echo "Created tag $TAG_NAME pointing to commit $GIT_COMMIT (SVN r$REV)" done
把脚本保存为import-tags.sh,赋予执行权限后运行即可:
chmod +x import-tags.sh ./import-tags.sh
验证结果
最后可以检查标签是否正确:
git checkout moduleX-1.0 # 查看moduleX的内容是否和SVN标签一致,同时其他模块是打标签时trunk的状态 ls -la git log --oneline
内容的提问来源于stack exchange,提问作者yurez
相关产品推荐
相关产品推荐

