SVN 项目迁移至 Git(Gitea)
现有项目代码 SVN 迁移到 Git
目标
- 将现有的 SVN 仓库管理方式迁移到 Gitea 中。
- 用 Gitea 补上 SVN 在日常开发中的短板。
前言
目前公司产品代码主要用 SVN 管理,更多是作为测试版本归档点使用:
- 测试通过的版本打一个版本号,整体打包后上传到 SVN。
- 版本之间的具体改动过程、功能迭代过程,基本不在 SVN 里体现。
对比 git 的使用方式,这种做法相当于只在“稳定节点”上有记录,开发过程中的细粒度提交、并行分支、合并记录都缺失,尤其在多人并行开发时,很难追踪是谁在什么时间改了什么。
因此,我们希望:
- 开发过程以 git + Gitea 为主,完整记录每一步改动;
- SVN 继续保留为“对外测试/归档”的渠道,两者之间通过版本号和 tag 对齐。
下面的迁移流程主要解决“存量项目怎么从 SVN 迁到 Gitea,并且不打乱原有测试流程”的问题。
SVN迁移到GIT流程
1. git 与 SVN 管理方式的差异(与迁移相关的部分)
这里只挑和迁移、日常工作流关系最大的一些差异说明:
- 版本管理方式不同
- 在 git 中,稳定测试版本只需要打一个 tag,例如
v1.2.3。 - Gitea 仓库对外只暴露 git 仓库,SVN 可以只保存这些带 tag 的稳定版本(继续做归档)。
- 在 git 中,稳定测试版本只需要打一个 tag,例如
- 分支与并行开发
- git 中可以为每个需求/缺陷开独立分支(如
feature/xxx、hotfix/xxx),分支之间可以方便地合并与回退。 - 这解决了“多线并行开发时,代码容易互相覆盖、不好回溯”的问题。
- git 中可以为每个需求/缺陷开独立分支(如
- 工单与合并记录
- 在 Gitea 中可以用 Issue 记录需求和问题,用 PR 记录合并过程;两者可以互相关联,后续追踪非常方便。
- 模块拆分与复用
- 一些通用模块(协议栈、公共库等)可以独立成仓库,用子模块/subtree 等方式复用,避免在 SVN 中一份代码复制到多个工程的情况。
了解这些差异后,就更容易设计“git + Gitea 负责日常开发,SVN 只做版本归档”的协作模式。
2. 迁移流程概览
整体可以分成两种思路:
- 只迁当前稳定版本到 git,后续开发都在 git 中进行(推荐起步方式)。
- 连同 SVN 历史记录一起迁到 git,尽量保留原来的提交历史。
无论哪种方式,第一步都是在 Gitea 上建好对应仓库,然后再决定是:
- 直接用当前 SVN 内容做一次“初始化提交”;还是
- 借助
git svn等工具,把 SVN 的历史一并导入。
下面分别展开说明。
2.1 在 Gitea 中创建空仓库并完成首次导入
- 在 Gitea 中,按照团队约定的组织/仓库命名规则,创建空仓库(可参考
gitea_org_create.md、gitea_repo_manage.md)。 - 从 SVN 检出当前稳定版本到本地工作区。
- 在工程根目录按团队要求补上基础文件,例如:
README.md、.gitignore、.clang-format等。 - 使用
git init初始化本地仓库。 - 使用
git add .将文件加入暂存区。 - 使用
git commit -m "init: 从 SVN 导入稳定版本 <SVN_REV>"进行首次提交,建议在提交信息中标注对应的 SVN 版本号或标签。 - 使用
git tag <tag_name>(例如svn-r1234或v1.0.0)给这个版本打上标签。 - 使用
git remote add origin <remote_url>关联到 Gitea 上的远程仓库地址。 - 使用
git push -u origin main将主分支推送到远程。 - 使用
git push origin --tags将标签推送到远程。
到这里,Gitea 上已经有了一个可用的 git 仓库,并且首个版本和原来的 SVN 稳定版本一一对应。
后续新的开发工作就可以基于这个仓库进行。
2.2 简单保留部分历史版本(手工方式)
如果不希望引入 git svn 等工具,但又希望在 git 中保留一些关键历史版本,可以用**“覆盖 + 提交”**的方式手工迁移几个重要节点:
- 先按 2.1 的方式,用最早想保留的那个 SVN 版本做一次初始化提交。
- 记录该 SVN 版本号,例如在提交说明里写上
SVN r100,并打一个标签(如svn-r100)。 - 然后用下一个版本的 SVN 内容覆盖当前工作区(可以重新从 SVN 检出,或者复制覆盖)。
- 使用
git status确认变更,git add .,再提交一次,提交信息中写上对应的 SVN 版本号。 - 如此循环,直到覆盖完所有你关心的历史版本。
这个方法操作相对简单,但缺点是:
- 提交粒度是“按版本打包”,而不是 SVN 原本的每一次提交。
如果项目历史很长、对精确追踪单次改动不敏感,这种方式通常足够用。
2.3 使用 git-svn 工具完整迁移历史
如果需要尽量保留 SVN 的历史提交记录,可以使用 git svn 工具进行迁移。
git svn clone -r5791:HEAD [svn_url] [new_name]
-r5791:HEAD表示从 SVN 的r5791版本开始到最新(HEAD)的所有提交都导入。r5791可以根据项目需求调整;通常可以从某个“起点版本”开始导入,而不是从项目最初始版本开始。- 具体版本号可以通过浏览器访问 SVN 仓库查看。
new_name是导入后本地 git 仓库的目录名,可以不写,默认与 SVN 仓库名相同。
迁移完成后,会在本地得到一个带有完整历史记录的 git 仓库。
接下来可以按 2.1 的方式,将该仓库推送到 Gitea:添加 remote、push 分支和 tag。
提示:
git svn适合作为一次性迁移工具,迁移完成并确认无误后,建议不再在日常开发中使用git svn,以避免误操作影响后续纯 git 仓库的使用。
3. 迁移后的日常管理方式
迁移完成后,建议采用以下原则来衔接原有 SVN 流程:
-
日常开发以 git + Gitea 为主
- 所有新功能、缺陷修复、分支管理、代码评审,都在 Gitea 上进行。
- SVN 不再用来承载开发分支和中间状态,只保留关键发布版本。
-
测试/发布版本继续同步到 SVN(按需)
- 当某个 tag 或 Release 版本需要交付测试或归档时,可以:
- 从 Gitea 仓库检出对应 tag;
- 按原有流程打包;
- 将打包结果拷贝到 SVN,作为“对外归档”的一个版本。
- 这样,原有依赖 SVN 的流程(如老工具脚本、老项目习惯)可以逐步、平滑地迁移,而不必一次性全部替换。
- 当某个 tag 或 Release 版本需要交付测试或归档时,可以:
-
版本对齐与追溯
- 建议在 SVN 的版本说明中标明对应的 git tag 或提交号,反之在 git 的 Release 说明中也可以备注“已同步到 SVN 的某路径”。
- 出现问题时,可以从 SVN 版本快速定位到 git 中的具体提交,反之亦然。
通过上述方式,可以在不打乱原有测试归档习惯的前提下,让新项目开发尽快转到 git + Gitea 的工作流上来,逐步减少对 SVN 的依赖,并且对团队管理上并未有明显变化。
- 感谢你赐予我前进的力量

