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