Git-SVN 混合开发,从入门到精通!

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 loggit 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 核心要点

  1. 克隆时使用 -s 参数 识别标准 SVN 结构
  2. 更新代码用 git svn rebase 而非 merge,保持线性历史
  3. 推送前必须先 rebase 确保基于最新 SVN 代码
  4. 本地可以随意使用 Git 特性 分支、暂存、变基等
  5. 推送到 SVN 时所有提交线性化 不支持合并提交
  6. 及时同步 每天开始和结束工作时 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 使用经验,或提出遇到的问题,我们一起探讨解决方案!

相关推荐
CoderYanger1 小时前
前端基础——JavaScript(基础语法)(下篇)
java·开发语言·前端·javascript·程序人生·面试·职场和发展
京师20万禁军教头1 小时前
39面向对象(高级)-设计模式
java·开发语言·设计模式
u1301301 小时前
GitHub 热榜项目:日榜(2026-09-05)
github
m4Rk_2 小时前
【论文阅读】Agent 记忆机制(61):CFGM——用粗到细的记忆落地贯通经验采集、知识蒸馏与在线纠错
论文阅读·人工智能·学习·开源·github
白山编程大哥2 小时前
Java 迭代器接口详解:从 Iterator 到 ListIterator 的完整指南
java·开发语言·windows
见叶之秋2 小时前
【C++】String类的使用(含模拟实现)
java·开发语言·c++
想吃火锅10052 小时前
【leetcode】42.接雨水js
开发语言·javascript·ecmascript
是2的10次方啊2 小时前
GitNexus:给 AI 代理装上代码知识图谱
github
雪芽蓝域zzs3 小时前
第十六节:递归组件实现无限层级折叠侧边栏菜单
开发语言·javascript·ecmascript