Git-SVN 混合开发:命令对照、工作流程与 15+ 实战技巧,一篇搞定!
摘要
本文详细介绍 Git-SVN 混合开发的完整方案,涵盖从安装配置到实战操作的全流程。通过 Git 命令与 SVN 命令的对照表格、15+ 个核心命令详解、以及真实场景下的工作流程,帮助你在 SVN 项目中享受 Git 的便利。无论你是被迫使用 SVN 的 Git 用户,还是想尝试 Git 功能的 SVN 团队,这篇文章都能让你快速上手 Git-SVN 混合开发模式。
在 SVN 项目中使用 Git 本地分支、暂存、变基等强大特性,同时保持与团队的 SVN 仓库同步!
当你加入一家使用 SVN 的公司,却习惯了 Git 的工作流程时,git-svn 就是你的救星。它允许你使用 Git 客户端操作 SVN 仓库,既能享受 Git 的本地分支、暂存区、交互式变基等强大功能,又能与团队的 SVN 仓库保持完美同步。本文将系统讲解 git-svn 的使用方法,让你在 SVN 环境中依然高效开发。
一、Git-SVN 基础入门
1.1 什么是 git-svn
git-svn 是 Git 官方提供的双向桥接工具,它让你可以用 Git 命令操作 SVN 仓库。本质上,git-svn 在本地维护一个完整的 Git 仓库,并在需要时将 Git 提交转换为 SVN 提交推送到远程 SVN 服务器。
工作原理示意:
1本地 Git 仓库 <-- git-svn --> 远程 SVN 仓库 2 (分支/暂存/变基) (trunk/branches/tags) 3
1.2 为什么需要 git-svn
SVN 与 Git 的核心差异对比表:
| 特性 | SVN | Git | git-svn 方案 |
|---|---|---|---|
| 版本管理 | 集中式 | 分布式 | 本地分布式,远程集中式 |
| 分支创建 | 慢,需服务器操作 | 快,本地秒级完成 | 本地使用 Git 分支 |
| 离线工作 | 不支持 | 完全支持 | 支持本地提交 |
| 提交粒度 | 粗,直接推送 | 细,可本地反复修改 | 本地细粒度,推送时合并 |
| 暂存区 | 无 | 有 | 使用 Git 暂存区 |
| 变基操作 | 不支持 | 支持 | 支持本地变基 |
使用场景:
- 公司强制使用 SVN,但你习惯 Git 工作流
- 团队迁移期间需要同时支持两种工具
- 需要在 SVN 项目中使用 Git 的高级特性
- 个人喜好 Git 命令行,但项目是 SVN
1.3 安装与配置
Windows 安装:
1# Git for Windows 默认包含 git-svn 2git --version 3# git version 2.40.0.windows.1 4 5# 检查 git-svn 是否可用 6git svn --version 7# git-svn version 2.40.0 (svn 1.14.1) 8
如果提示找不到 git-svn,需要安装完整版 Git:
1# 下载 Git 完整安装包(包含 SVN 支持) 2# https://git-scm.com/download/win 3
Linux 安装:
1# Ubuntu/Debian 2sudo apt-get install git-svn 3 4# CentOS/RHEL 5sudo yum install git-svn 6 7# 验证安装 8git svn --version 9# git-svn version 2.34.1 (svn 1.14.1) 10
Mac 安装:
1# Homebrew 安装 2brew install git 3 4# 检查是否包含 git-svn 5git svn --version 6# git-svn version 2.39.2 (svn 1.14.2) 7
全局配置优化:
1# 配置用户信息(与 SVN 账号保持一致) 2git config --global user.name "zhangsan" 3git config --global user.email "zhangsan@company.com" 4 5# 设置自动换行(避免跨平台问题) 6git config --global core.autocrlf input 7 8# 优化 git-svn 性能 9git config --global svn.rmdir true 10# 自动删除空目录 11 12git config --global svn.pushmergeinfo false 13# 不推送 mergeinfo 属性(避免冲突) 14
1.4 SVN 仓库结构说明
标准 SVN 仓库结构:
1svn://server.com/project/ 2├── trunk/ # 主干(相当于 Git 的 main/master) 3├── branches/ # 分支目录 4│ ├── feature-A/ 5│ └── release-1.0/ 6└── tags/ # 标签目录 7 ├── v1.0.0/ 8 └── v1.1.0/ 9
非标准结构(部分公司自定义):
1svn://server.com/project/ 2├── main/ # 主干(非 trunk) 3├── dev/ # 开发分支 4└── prod/ # 生产分支 5
二、Git-SVN 核心操作
2.1 克隆 SVN 仓库
标准结构克隆(推荐):
1# 克隆标准 SVN 仓库(trunk/branches/tags) 2git svn clone svn://server.com/project -s 3 4# 参数说明: 5# -s 或 --stdlayout:标准布局,自动识别 trunk/branches/tags 6# 等价于: 7# -T trunk -b branches -t tags 8
克隆过程输出示例:
1Initialized empty Git repository in /home/user/project/.git/ 2r1 = a1b2c3d4e5f6 (refs/remotes/origin/trunk) 3r2 = f6e5d4c3b2a1 (refs/remotes/origin/trunk) 4... 5Checked out HEAD: 6 svn://server.com/project/trunk r150 7# 克隆完成,当前在 trunk 对应的分支 8
非标准结构克隆:
1# 指定自定义分支和标签路径 2git svn clone svn://server.com/project \ 3 -T main \ 4 -b dev \ 5 -b release \ 6 -t versions 7 8# 参数说明: 9# -T main:主干在 main 目录 10# -b dev:分支在 dev 目录 11# -b release:另一个分支目录 12# -t versions:标签在 versions 目录 13
仅克隆主干(快速克隆):
1# 只克隆 trunk,不包含分支和标签 2git svn clone svn://server.com/project/trunk myproject 3 4cd myproject 5# 立即可用,无需等待全部分支历史 6
克隆指定版本范围(提速):
1# 仅克隆最近 100 个版本 2git svn clone svn://server.com/project -s -r 100:HEAD 3 4# 参数说明: 5# -r 100:HEAD:从版本 100 克隆到最新版本 6# 历史提交较多时可大幅提速 7
克隆完成后的目录结构:
1cd myproject 2ls -la 3# .git/ # Git 仓库目录 4# .gitignore # 自动生成的忽略文件 5# src/ # 项目源码 6# README.md 7 8git branch -a 9# * master # 本地主分支(对应 trunk) 10# remotes/origin/trunk # SVN trunk 的 Git 引用 11# remotes/origin/feature-A # SVN 分支的 Git 引用 12
2.2 日常提交工作流
Git 风格的本地提交:
1# 修改文件 2echo "new feature" >> src/main.py 3 4# 查看状态 5git status 6# On branch master 7# Changes not staged for commit: 8# modified: src/main.py 9 10# 添加到暂存区 11git add src/main.py 12 13# 本地提交(不影响 SVN) 14git commit -m "Add new feature" 15# [master a1b2c3d] Add new feature 16# 1 file changed, 1 insertion(+) 17 18# 此时 SVN 服务器完全不知情 19
推送到 SVN 服务器:
1# 先更新 SVN 最新代码(必须) 2git svn rebase 3# Current branch master is up to date. 4 5# 推送本地 Git 提交到 SVN 6git svn dcommit 7# Committing to svn://server.com/project/trunk ... 8# M src/main.py 9# Committed r151 10# r151 = f1e2d3c4b5a6 (refs/remotes/origin/trunk) 11 12# dcommit 做了什么: 13# 1. 将本地 Git 提交转换为 SVN 提交 14# 2. 推送到 SVN 服务器 15# 3. 更新本地 Git 引用以匹配 SVN 版本号 16
多次本地提交后再推送:
1# 第一次本地提交 2git add file1.py 3git commit -m "Implement feature part 1" 4# [master a1b2c3d] Implement feature part 1 5 6# 第二次本地提交 7git add file2.py 8git commit -m "Implement feature part 2" 9# [master b2c3d4e] Implement feature part 2 10 11# 第三次本地提交 12git add test.py 13git commit -m "Add tests" 14# [master c3d4e5f] Add tests 15 16# 查看本地提交历史 17git log --oneline -3 18# c3d4e5f Add tests 19# b2c3d4e Implement feature part 2 20# a1b2c3d Implement feature part 1 21 22# 一次性推送到 SVN 23git svn rebase 24git svn dcommit 25# Committing to svn://server.com/project/trunk ... 26# ... 27# Committed r152 28# Committed r153 29# Committed r154 30# 每个 Git 提交转换为一个 SVN 版本号 31
2.3 更新代码
拉取 SVN 最新代码:
1# 使用 rebase 而不是 fetch + merge 2git svn rebase 3 4# 输出示例: 5# First, rewinding head to replay your work on top of it... 6# Fast-forwarded master to refs/remotes/origin/trunk 7# r152 = a1b2c3d4e5f6 (refs/remotes/origin/trunk) 8# r153 = b2c3d4e5f6a7 (refs/remotes/origin/trunk) 9
为什么用 git svn rebase 而不是 git svn fetch + git merge?
| 操作 | 效果 | 适用场景 |
|---|---|---|
| git svn rebase | 变基,保持线性历史 | 日常更新(推荐) |
| git svn fetch + git merge | 合并,产生合并提交 | SVN 不支持,会出错 |
| git svn fetch + 手动操作 | 仅获取,不合并 | 检查更新内容 |
有本地未提交修改时更新:
1# 场景:本地有修改,但还没 commit 2git status 3# Changes not staged for commit: 4# modified: src/utils.py 5 6# 方法1:暂存修改 7git stash 8# Saved working directory and index state WIP on master 9 10git svn rebase 11# 更新完成 12 13git stash pop 14# 恢复修改 15# On branch master 16# Changes not staged for commit: 17# modified: src/utils.py 18 19# 方法2:直接提交后再 rebase 20git add src/utils.py 21git commit -m "WIP: update utils" 22git svn rebase 23# 本地提交会自动变基到最新 SVN 代码之上 24
冲突解决:
1git svn rebase 2# CONFLICT (content): Merge conflict in src/main.py 3# error: could not apply a1b2c3d... Add feature 4# Resolve all conflicts manually, mark them as resolved with 5# "git add/rm <conflicted_files>", then run "git rebase --continue". 6 7# 手动编辑冲突文件 8vim src/main.py 9# <<<<<<< HEAD 10# def old_function(): 11# pass 12# ======= 13# def new_function(): 14# pass 15# >>>>>>> Add feature 16 17# 解决冲突后标记为已解决 18git add src/main.py 19 20# 继续 rebase 21git rebase --continue 22# [detached HEAD f1e2d3c] Add feature 23# 1 file changed, 3 insertions(+) 24 25# 如果无法解决,放弃本次更新 26git rebase --abort 27
2.4 分支管理
列出所有分支:
1# 查看本地和远程分支 2git branch -a 3# * master # 当前本地分支 4# remotes/origin/trunk # SVN trunk 5# remotes/origin/feature-A # SVN 分支 6# remotes/origin/release-1.0 # SVN 发布分支 7# remotes/origin/tags/v1.0.0 # SVN 标签 8
创建本地 Git 分支(不影响 SVN):
1# 基于当前代码创建本地特性分支 2git checkout -b my-feature 3# Switched to a new branch 'my-feature' 4 5# 在本地分支上开发 6git add new_feature.py 7git commit -m "Implement new feature" 8# [my-feature a1b2c3d] Implement new feature 9 10# 查看分支 11git branch 12# master 13# * my-feature 14 15# 切回主分支并合并 16git checkout master 17git merge my-feature 18# Updating f1e2d3c..a1b2c3d 19# Fast-forward 20# new_feature.py | 10 ++++++++++ 21# 1 file changed, 10 insertions(+) 22 23# 推送到 SVN(SVN 只看到最终结果) 24git svn dcommit 25# Committing to svn://server.com/project/trunk ... 26# Committed r155 27
切换到 SVN 分支:
1# 基于远程 SVN 分支创建本地跟踪分支 2git checkout -b feature-A remotes/origin/feature-A 3# Switched to a new branch 'feature-A' 4# Branch 'feature-A' set up to track remote branch 'origin/feature-A' 5 6# 在该分支上开发 7git add fix.py 8git commit -m "Fix bug in feature A" 9 10# 推送到 SVN 的 feature-A 分支 11git svn dcommit 12# Committing to svn://server.com/project/branches/feature-A ... 13# Committed r156 14
从 SVN 创建新分支:
1# SVN 分支本质是目录拷贝,需要用 SVN 命令创建 2# 方法1:使用 svn 命令(如果安装了 SVN 客户端) 3svn copy svn://server.com/project/trunk \ 4 svn://server.com/project/branches/new-feature \ 5 -m "Create new feature branch" 6 7# 方法2:在 SVN 服务器 Web 界面创建 8 9# 然后在 git-svn 中更新分支列表 10git svn fetch 11# 拉取新分支信息 12 13git checkout -b new-feature remotes/origin/new-feature 14# 切换到新分支进行开发 15
2.5 查看历史与信息
查看 SVN 版本信息:
1# 显示当前 SVN 版本号和 URL 2git svn info 3# Path: . 4# URL: svn://server.com/project/trunk 5# Repository Root: svn://server.com/project 6# Revision: 155 7# Node Kind: directory 8# Last Changed Author: zhangsan 9# Last Changed Rev: 155 10# Last Changed Date: 2026-09-04 14:30:22 +0800 11
查看 Git 提交与 SVN 版本的对应关系:
1# 查看提交历史(显示 SVN 版本号) 2git log --oneline --decorate 3# a1b2c3d (HEAD -> master, origin/trunk) Add feature (r155) 4# f1e2d3c Fix bug (r154) 5# e5f6a7b Initial commit (r153) 6 7# 查看详细的 SVN 映射信息 8git log -1 9# commit a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 10# Author: zhangsan <zhangsan@company.com> 11# Date: Thu Sep 4 14:30:22 2026 +0800 12# 13# Add feature 14# 15# git-svn-id: svn://server.com/project/trunk@155 uuid-here 16
查找指定 SVN 版本号对应的 Git 提交:
1# 根据 SVN 版本号查找 Git 提交 2git svn find-rev r155 3# a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 4 5# 反向查找:Git 提交对应的 SVN 版本号 6git svn find-rev a1b2c3d 7# 155 8
三、Git-SVN 命令大全(15+ 实战技巧)
3.1 基础命令速查
| 命令 | 功能 | SVN 等价命令 |
|---|---|---|
| git svn clone | 克隆 SVN 仓库 | svn checkout |
| git svn rebase | 更新代码 | svn update |
| git svn dcommit | 推送提交 | svn commit |
| git svn fetch | 仅拉取不合并 | svn update --dry-run |
| git svn info | 查看 SVN 信息 | svn info |
| git svn log | 查看 SVN 日志 | svn log |
| git svn blame | 逐行追溯 | svn blame |
| git svn show-ignore | 显示忽略规则 | svn propget svn:ignore |
| git svn create-ignore | 生成 .gitignore | - |
| git svn find-rev | 版本号转换 | - |
3.2 克隆与初始化命令
1. 标准克隆:
1git svn clone svn://server.com/project -s 2# 克隆标准 SVN 仓库(trunk/branches/tags) 3
2. 指定版本范围克隆(提速):
1git svn clone svn://server.com/project -s -r 1000:HEAD 2# 仅克隆版本 1000 到最新,大幅减少克隆时间 3
3. 克隆时指定作者映射:
1# 创建作者映射文件 2cat > authors.txt <<EOF 3zhangsan = Zhang San <zhangsan@company.com> 4lisi = Li Si <lisi@company.com> 5wangwu = Wang Wu <wangwu@company.com> 6EOF 7 8# 使用作者映射克隆 9git svn clone svn://server.com/project -s --authors-file=authors.txt 10# SVN 用户名自动转换为 Git 格式的作者信息 11
4. 克隆指定子目录:
1git svn clone svn://server.com/project/trunk/subdir myproject 2# 仅克隆 trunk 下的 subdir 子目录 3
5. 初始化已存在的 Git 仓库:
1# 场景:已有 Git 仓库,想连接到 SVN 2cd existing-git-repo 3 4git svn init svn://server.com/project -s 5# Initialized empty Git svn repository 6 7git svn fetch 8# 拉取 SVN 历史并关联 9
3.3 更新与同步命令
6. 标准更新:
1git svn rebase 2# 拉取 SVN 最新代码并变基本地提交 3
7. 仅拉取不变基:
1git svn fetch 2# 仅更新 refs/remotes/origin/* 引用,不影响工作区 3
8. 更新所有分支:
1git svn fetch --all 2# 更新所有 SVN 分支和标签的 Git 引用 3
9. 强制覆盖本地修改:
1# 场景:本地修改不要了,直接用 SVN 最新代码 2git reset --hard remotes/origin/trunk 3# HEAD is now at a1b2c3d Latest SVN commit 4
3.4 提交与推送命令
10. 标准推送:
1git svn dcommit 2# 将本地 Git 提交逐个转换为 SVN 提交 3
11. 推送前预览:
1git svn dcommit --dry-run 2# 显示将要推送的提交,但不实际执行 3# Committing to svn://server.com/project/trunk ... 4# diff-tree a1b2c3d~1 a1b2c3d 5# (dry run; not actually committing) 6
12. 推送时自动 rebase:
1git svn dcommit --rebase 2# 推送前先自动 rebase,避免冲突 3# 等价于:git svn rebase && git svn dcommit 4
13. 推送指定范围的提交:
1# 仅推送最近 3 个提交 2git svn dcommit HEAD~3..HEAD 3# 推送从 HEAD~3 到 HEAD 的提交 4
14. 推送到指定 SVN 分支:
1# 场景:在本地 Git 分支开发,推送到 SVN 的特定分支 2git checkout my-feature 3git svn dcommit --commit-url=svn://server.com/project/branches/feature-A 4# 推送到 SVN 的 feature-A 分支而非 trunk 5
3.5 信息查询命令
15. 查看 SVN 信息:
1git svn info 2# 显示当前目录对应的 SVN URL、版本号、作者等 3
16. 查看 SVN 日志:
1git svn log 2# 显示 SVN 风格的日志(带版本号) 3# r155 | zhangsan | 2026-09-04 14:30:22 +0800 | 1 line 4# Add feature 5
17. 逐行追溯(blame):
1git svn blame src/main.py 2# 显示每行代码最后修改的 SVN 版本号和作者 3# r153 zhangsan 1) def main(): 4# r154 lisi 2) print("Hello") 5# r155 wangwu 3) return 0 6
18. 查找版本号:
1# Git 提交哈希转 SVN 版本号 2git svn find-rev a1b2c3d 3# 155 4 5# SVN 版本号转 Git 提交哈希 6git svn find-rev r155 7# a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 8
3.6 忽略规则命令
19. 显示 SVN 忽略规则:
1git svn show-ignore 2# 显示 SVN 的 svn:ignore 属性 3# *.o 4# *.pyc 5# __pycache__/ 6
20. 生成 .gitignore 文件:
1git svn show-ignore > .gitignore 2# 将 SVN 忽略规则转换为 Git 格式并保存 3 4git add .gitignore 5git commit -m "Add .gitignore from SVN ignore rules" 6
21. 创建全局忽略配置:
1git svn create-ignore 2# 自动生成 .gitignore 并应用到所有子目录 3# Applying svn:ignore from trunk to .gitignore 4
3.7 高级技巧命令
22. 清理空目录:
1# SVN 允许空目录,Git 不跟踪空目录 2git svn gc 3# 清理 .git/svn 目录中的临时文件 4 5git svn mkdirs 6# 创建 SVN 中存在的空目录(在本地 Git 仓库中) 7
23. 重置 SVN 映射:
1# 场景:SVN 仓库重组,需要重新映射 2git svn reset -r 100 3# 重置到 SVN 版本 100,重新开始同步 4
24. 显示未推送的本地提交:
1# 查看哪些 Git 提交还没推送到 SVN 2git log remotes/origin/trunk..HEAD --oneline 3# a1b2c3d Local commit 3 4# b2c3d4e Local commit 2 5# c3d4e5f Local commit 1 6# 这 3 个提交还未 dcommit 到 SVN 7
25. 变基到指定 SVN 版本:
1git svn rebase --onto=remotes/origin/trunk@150 2# 变基到 SVN 版本 150,忽略 151-155 的提交 3
四、实战工作流程
4.1 单人开发工作流
1# 1. 克隆 SVN 仓库 2git svn clone svn://server.com/project -s 3cd project 4 5# 2. 创建本地功能分支 6git checkout -b feature-login 7 8# 3. 开发并多次本地提交 9git add login.py 10git commit -m "Add login page" 11 12git add auth.py 13git commit -m "Add authentication logic" 14 15git add test_login.py 16git commit -m "Add login tests" 17 18# 4. 切回主分支并合并 19git checkout master 20git merge feature-login 21# Fast-forward 22 23# 5. 更新 SVN 最新代码 24git svn rebase 25# Current branch master is up to date. 26 27# 6. 推送到 SVN 28git svn dcommit 29# Committed r156 30# Committed r157 31# Committed r158 32 33# 7. 删除本地功能分支 34git branch -d feature-login 35# Deleted branch feature-login 36
4.2 多人协作工作流
1# 上午开始工作 2git svn rebase 3# 拉取同事昨天推送的代码 4# r160 = a1b2c3d (refs/remotes/origin/trunk) 5# r161 = b2c3d4e (refs/remotes/origin/trunk) 6 7# 本地开发 8git add new_feature.py 9git commit -m "Implement feature X" 10 11# 午休后同步 12git svn rebase 13# 拉取同事上午推送的代码 14# r162 = c3d4e5f (refs/remotes/origin/trunk) 15 16# 继续开发 17git add enhancement.py 18git commit -m "Enhance feature X" 19 20# 下班前推送 21git svn rebase 22# 拉取同事下午推送的代码(如有) 23 24git svn dcommit 25# 推送自己的 2 个提交 26# Committed r163 27# Committed r164 28
4.3 紧急 Bug 修复流程
1# 场景:线上发现紧急 Bug,需要立即修复 2 3# 1. 暂存当前工作(未完成的功能) 4git stash 5# Saved working directory and index state WIP on master 6 7# 2. 更新到最新代码 8git svn rebase 9 10# 3. 创建 bugfix 分支 11git checkout -b hotfix-critical-bug 12 13# 4. 快速修复并测试 14vim src/payment.py 15# 修复支付模块的空指针异常 16 17git add src/payment.py 18git commit -m "Fix NullPointerException in payment module" 19 20# 5. 切回主分支并合并 21git checkout master 22git merge hotfix-critical-bug 23# Fast-forward 24 25# 6. 立即推送到 SVN 26git svn dcommit 27# Committed r165 28 29# 7. 恢复之前的工作 30git stash pop 31# On branch master 32# Changes not staged for commit: 33# modified: src/new_feature.py 34 35# 8. 清理 bugfix 分支 36git branch -d hotfix-critical-bug 37
4.4 团队分支管理流程
1# 场景:团队使用 SVN 的 feature 分支开发新功能 2 3# 1. 列出所有 SVN 分支 4git branch -r 5# remotes/origin/trunk 6# remotes/origin/feature-payment-v2 7# remotes/origin/feature-search-engine 8 9# 2. 切换到指定 SVN 分支 10git checkout -b payment-v2 remotes/origin/feature-payment-v2 11# Switched to a new branch 'payment-v2' 12 13# 3. 在该分支开发 14git add payment_v2.py 15git commit -m "Implement payment v2 interface" 16 17# 4. 推送到 SVN 分支 18git svn rebase 19git svn dcommit 20# Committing to svn://server.com/project/branches/feature-payment-v2 ... 21# Committed r166 22 23# 5. 功能完成后,在 SVN 中合并分支到 trunk 24# (通常用 SVN 命令或 Web 界面完成) 25svn merge svn://server.com/project/branches/feature-payment-v2 \ 26 svn://server.com/project/trunk 27 28# 6. 切回本地 master 分支并更新 29git checkout master 30git svn rebase 31# 拉取合并后的代码 32
五、常见问题与解决方案
5.1 推送失败:SVN 有新提交
错误信息:
1git svn dcommit 2# Committing to svn://server.com/project/trunk ... 3# Update of 'trunk' failed. 4# error: svn commit failed 5
原因:
推送前有其他人推送了新代码,导致本地不是基于最新版本。
解决方案:
1# 先更新代码 2git svn rebase 3# First, rewinding head to replay your work on top of it... 4# r167 = d4e5f6a (refs/remotes/origin/trunk) 5 6# 解决冲突(如有) 7# vim conflicted_file.py 8# git add conflicted_file.py 9# git rebase --continue 10 11# 再推送 12git svn dcommit 13# Committed r168 14
5.2 克隆速度慢
问题:
SVN 仓库历史提交数万个,克隆需要数小时。
解决方案:
1# 方案1:仅克隆最近版本 2git svn clone svn://server.com/project -s -r 5000:HEAD 3# 从版本 5000 开始克隆,忽略更早历史 4 5# 方案2:仅克隆 trunk 6git svn clone svn://server.com/project/trunk myproject 7# 不包含分支和标签,速度最快 8 9# 方案3:浅克隆(需要 Git 2.30+) 10git svn clone svn://server.com/project -s --shallow 11# 创建浅克隆,历史提交不完整但可用 12
5.3 分支推送到错误位置
问题:
本地 Git 分支推送时到了 trunk 而非预期的 SVN 分支。
解决方案:
1# 指定推送目标 URL 2git svn dcommit --commit-url=svn://server.com/project/branches/my-feature 3# 强制推送到指定 SVN 分支 4 5# 或者在分支创建时正确设置跟踪 6git checkout -b my-feature remotes/origin/my-feature 7# 自动跟踪对应的 SVN 分支 8
5.4 忘记 rebase 直接 merge 导致错误
问题:
1git svn fetch 2git merge remotes/origin/trunk 3# 产生了合并提交 4 5git svn dcommit 6# error: merge commits are not supported with git-svn 7
原因:
SVN 不支持 Git 的合并提交(多父节点)。
解决方案:
1# 撤销合并提交 2git reset --hard HEAD~1 3 4# 正确方式:使用 rebase 5git svn rebase 6# 变基保持线性历史 7 8git svn dcommit 9# 推送成功 10
5.5 修改已推送的提交
问题:
推送到 SVN 后发现提交有误,想修改。
解决方案:
1# SVN 不支持修改历史,只能追加新提交 2git add fixed_file.py 3git commit -m "Fix typo in previous commit" 4 5git svn dcommit 6# Committed r169 7 8# 注意:不要使用 git commit --amend 或 git rebase -i 9# 已推送的 Git 提交对应 SVN 版本号,改写历史会导致不一致 10
5.6 空目录丢失
问题:
SVN 中的空目录在 Git 中消失了。
原因:
Git 不跟踪空目录,只跟踪文件。
解决方案:
1# 方案1:在空目录中放置 .gitkeep 文件 2mkdir empty_dir 3touch empty_dir/.gitkeep 4git add empty_dir/.gitkeep 5git commit -m "Keep empty directory" 6 7# 方案2:使用 git-svn 自动创建空目录 8git svn mkdirs 9# 根据 SVN 信息在本地创建所有空目录 10
六、Git 与 SVN 命令对照速查表
| 操作 | SVN 命令 | Git 命令 | Git-SVN 命令 |
|---|---|---|---|
| 克隆仓库 | svn checkout URL | git clone URL | git svn clone URL -s |
| 更新代码 | svn update | git pull | git svn rebase |
| 提交修改 | svn commit -m "msg" | git commit -m "msg" | git commit + git svn dcommit |
| 查看状态 | svn status | git status | git status |
| 查看差异 | svn diff | git diff | git diff |
| 查看日志 | svn log | git log | git log 或 git svn log |
| 添加文件 | svn add file | git add file | git add file |
| 删除文件 | svn delete file | git rm file | git rm file |
| 移动文件 | svn move old new | git mv old new | git mv old new |
| 创建分支 | svn copy trunk branches/name | git branch name | git branch name (本地) |
| 切换分支 | svn switch URL | git checkout branch | git checkout branch |
| 合并分支 | svn merge URL | git merge branch | git merge branch |
| 撤销修改 | svn revert file | git restore file | git restore file |
| 忽略文件 | svn propset svn:ignore | .gitignore | git svn show-ignore |
| 查看信息 | svn info | - | git svn info |
| 逐行追溯 | svn blame file | git blame file | git svn blame file |
七、总结与最佳实践
7.1 核心要点
- 克隆时使用
-s参数 识别标准 SVN 结构 - 更新代码用
git svn rebase而非merge,保持线性历史 - 推送前必须先
rebase确保基于最新 SVN 代码 - 本地可以随意使用 Git 特性 分支、暂存、变基等
- 推送到 SVN 时所有提交线性化 不支持合并提交
- 及时同步 每天开始和结束工作时
git svn rebase
7.2 推荐工作流
1# 每日工作标准流程 2git svn rebase # 开始工作前更新 3git checkout -b my-feature # 创建功能分支 4# ...开发... 5git add . 6git commit -m "Feature complete" 7git checkout master 8git merge my-feature # 合并到主分支 9git svn rebase # 推送前再次更新 10git svn dcommit # 推送到 SVN 11git branch -d my-feature # 清理功能分支 12
7.3 注意事项
| 建议 | 说明 |
|---|---|
| 推送前必须 rebase | 避免推送失败 |
| 不要改写已推送的历史 | SVN 不支持 |
| 本地分支随意创建 | 不影响 SVN |
| 使用 .gitignore | 避免提交临时文件 |
| 定期 git gc | 清理本地仓库 |
| 备份重要分支 | Git 分支仅在本地 |
7.4 性能优化建议
1# 克隆时限制版本范围 2git svn clone -r 1000:HEAD 3 4# 启用自动删除空目录 5git config svn.rmdir true 6 7# 禁用 mergeinfo(避免冲突) 8git config svn.pushmergeinfo false 9 10# 定期清理 11git svn gc 12git gc --aggressive 13
7.5 快速参考卡片
1常用命令: 2 克隆: git svn clone <URL> -s 3 更新: git svn rebase 4 推送: git svn dcommit 5 信息: git svn info 6 日志: git svn log 7 8工作流: 9 1. git svn rebase(更新) 10 2. git add + git commit(本地提交) 11 3. git svn rebase(推送前更新) 12 4. git svn dcommit(推送) 13 14疑难杂症: 15 推送失败 → git svn rebase 后重试 16 克隆慢 → 加 -r 参数限制版本 17 空目录丢失 → git svn mkdirs 18 合并提交错误 → 用 rebase 代替 merge 19
结语
Git-SVN 让你在 SVN 环境中享受 Git 的强大功能,是过渡期或混合环境的最佳选择。掌握本文的 15+ 命令和工作流程,你就能在 SVN 项目中高效开发,同时保持与团队的无缝协作。
欢迎在评论区分享你的 Git-SVN 使用经验,或提出遇到的问题,我们一起探讨解决方案!
《Git-SVN 混合开发,从入门到精通!》 是转载文章,点击查看原文。

