一、为什么从 SVN 迁移到 Git?

在过去很长一段时间,很多公司都使用 SVN 作为版本控制工具。随着 Git 的普及,以及 CI/CD 等现代开发工具链的兴起,越来越多团队考虑从 SVN 迁移到 Git。

本篇博客记录我实际操作的一次 SVN 到 Git 的迁移过程:我想将一个SVN老项目带走,因为SVN离开公司的中心服务器原来的提交历史等信息就会丢失,我自然就想到Git的自身就能进行版本控制的能力,然后我会出差来到一个无网络环境(局域网),此时我将进行一些开发做一些提交,最后回到公司将这些提交集成回公司的中心服务器.

Git的优势:

  • Git 分支管理灵活,支持分布式开发

  • 支持离线提交、离线历史查看

  • 集成更丰富的代码托管平台(GitHub、GitLab、Gitea 等)

  • 配合 CI/CD、Pull Request 等现代开发流程更友好


二、环境准备

工具:

如果你不熟悉Git可以看我的这篇博客:在Unity环境中使用Git进行版本控制(入门篇)_unity git-CSDN博客

安装了Git后在一个文件夹下验证一下环境:

在任意一个目录下右键发现一个Open Git Bash 验证下面两个命令

git --version
git svn --version

 


三、获取 SVN 作者信息映射表(可选)

如果不关心作者信息,则建议直接省略,省略这步则会直接使用SVN中的作者信息

如果想让 svn 的历史作者正确映射成 git 格式,需要一份作者映射表。

生成作者映射文件:

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

然后根据需要编辑 userinfo.txt,把 SVN 用户名改成人名邮箱等 Git 风格。


四、执行 git-svn 克隆

进入一个空目录(该目录是用来存放项目的):

git svn clone https://svn服务器地址/项目路径 

clone后面加上svn的地址就行了,但是也可以加一些参数,但是我对此不是很懂,所以没有使用,有需要则需要更细致的查看git的官方文档.

要注意的是大概率会弹出一个弹窗要求你信任证书

因为如果 svn 是 https 且有自签证书,会提示信任证书,选择 t (临时) 或 p (永久信任)。

然后要求你输入你的svn账号密码.

参数说明:

参数 含义
--no-metadata 不保留 git-svn 内部元数据
--authors-file 使用刚才的作者映射表
--stdlayout 如果 SVN 仓库有标准目录结构(trunk/branches/tags)可以加上


五、离线开发与本地提交

Git 的好处就是,即使没网,也可以这样:

git add .
git commit -m "第一次离线开发提交"
git commit -m "第二次离线开发提交"

不用担心 SVN 连接失败。

你可以使用GUI工具,我上面提到博客也对此有说明.


六、恢复网络后同步回 SVN

先拉取一下 SVN 最新:

git svn fetch

然后同步你的历史提交:

git rebase remotes/git-svn
git svn dcommit

这样,你所有本地 Git 提交,会逐个同步回 SVN。

这里要提一下:这个由svn迁移的git仓库内部仍保持着对原来svn服务器的联系,所以你仍然可以更新或推送代码.所以这里的需要专门的命令(如 git svn dcommit而不是git commit)

Git SVN 工作流细致讲解(git svn fetchgit rebase remotes/git-svngit svn dcommit

这里用一个完整的场景,详细讲解 Git 与 SVN 协作中的三个核心命令的作用和顺序:


① 克隆仓库(git svn clone

首先,我通过以下命令克隆 SVN 仓库:

git svn clone <SVN 仓库地址>

此时:

  • SVN 服务器当前版本是 r100

  • Git 会创建一个远程跟踪分支 remotes/git-svn,指向 SVN 最新提交 r100;

  • Git 还会基于 remotes/git-svn 创建一个本地分支 master,作为本地工作分支,也指向 r100。


② 本地开发

我在本地 master 分支上进行了三次提交,分别是:

  • 提交 A

  • 提交 B

  • 提交 C

此时本地提交历史如下:

r100 → A → B → C(master)

remotes/git-svn 依然指向 r100:

remotes/git-svn → r100

③ 同事推送了新提交到 SVN

假设此时我的同事在 SVN 服务器上进行了 5 次提交,SVN 版本推进到了 r105


④ 同步 SVN 最新提交(git svn fetch

我需要拉取最新的 SVN 提交,执行命令:

git svn fetch

此时:

  • remotes/git-svn 被更新到 r105;

  • 本地 master 分支不变,仍基于 r100。

当前状态:

remotes/git-svn → r105
master → r100 → A → B → C

⑤ 变基到最新 SVN 提交(git rebase remotes/git-svn

为了让我的提交基于 SVN 最新版本,我执行:

git rebase remotes/git-svn

这个命令做了三件事:

  1. 临时“摘取”我本地的提交 A、B、C;

  2. master 分支指针移动到 remotes/git-svn(r105);

  3. 依次把 A、B、C 重放到 r105 之后,形成新的提交链(过程中若有冲突需解决):

r105 → A′ → B′ → C′(master)

(注:A′、B′、C′ 是变基后的新提交对象)


⑥ 推送到 SVN(git svn dcommit

变基完成后,我执行:

git svn dcommit

这条命令会:

  1. 将 A′、B′、C′ 提交到 SVN 服务器,生成新版本 r106、r107、r108;

  2. 自动更新 remotes/git-svn,指向最新的 SVN 提交 r108;

  3. 本地 master 也指向 r108,保持同步。

最终状态:

SVN 服务器:r106 → r107 → r108
remotes/git-svn → r108
master → r108

✅ 全流程示意图:
# 初始状态
remotes/git-svn → r100
master → r100 → A → B → C

# 同事提交后
remotes/git-svn → r105
master(不变)

# 执行 git svn fetch
remotes/git-svn → r105
master(不变)

# 执行 git rebase remotes/git-svn
remotes/git-svn → r105
master → r105 → A′ → B′ → C′(变基)

# 执行 git svn dcommit
SVN 服务器 → r106 → r107 → r108
remotes/git-svn → r108
master → r108

✅ 关键总结:
  • remotes/git-svn 仅是 SVN 服务器最新提交的“镜像”,不会存储你的本地提交

  • git rebase remotes/git-svn 会把你的本地提交“重放”到 SVN 最新提交之后,让提交链保持线性;

  • git svn dcommit 会按顺序把你的提交推送到 SVN,并自动更新本地 remotes/git-svnmaster


七、推送到云端 Git 仓库

如果你还想同步备份到云 Git 仓库(比如 Gitee、GitHub、GitLab):

git remote add origin https://你云端Git地址.git
git push -u origin master

-u的意思是将名为origin的仓库设为默认推送或拉取的仓库

以后想同步:

git push
git pull

此时SVN中心服务器和Git云服务器都能和你这个仓库交互.

 其实这里我还遇到一个问题:我本想使用gitee作为我的云,但是遭遇了推送失败,原因是免费版本的云服务器限制单个文件要小于100MB,很不巧我的项目的历史提交中包含这么大的文件,所以我没法使用gitee,没办法我临时搭建一个自己的git服务器,我以前使用过gitea,轻量强大

Gitea简单部署:

https://github.com/go-gitea/gitea

从发布版里面找windows的64版本,下载下来就行了(我是临时用用,建议从官方文档查看规范的部署流程).

下载下来后,放在一个专门的目录下就完成了(这个目录就是你的服务器了) ,此时启动该exe

我的理解本质就是一个大的后端项目,访问该地址(ctrl+左键)

要求数据库,我选择SQLite,这样我不需要部署数据库,公司名填一下就可以安装了

默认第一个注册用户是管理员,后续操作和Github没有太大差别. 


八、日常双轨工作流建议

场景 命令
从 SVN 拉取更新 git svn fetch
把本地改动同步到 SVN git svn dcommit
离线开发 git commit
推送云端 Git git push origin master
拉取云端 Git git pull origin master

九、常见问题

1. SSL 证书错误怎么办?

SVN 自签证书的话,第一次拉取时会弹出信任确认,选 tp


2. 推送到 Git 报错:remote contains work that you do not have locally?

远程仓库可能有默认 README、.gitignore,你先:

git pull origin master --rebase

然后再推:

git push

3. 有没有办法以后彻底脱离 SVN?

可以,后续可以做一次仓库“脱 SVN 清洗”,删掉 .git/config 里的 svn-remote 部分,然后强制推送纯 Git 历史。

Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐