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

作者:重生之我来学Python日期:2026/9/7

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 的核心差异对比表:

特性SVNGitgit-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 URLgit clone URLgit svn clone URL -s
更新代码svn updategit pullgit svn rebase
提交修改svn commit -m "msg"git commit -m "msg"git commit + git svn dcommit
查看状态svn statusgit statusgit status
查看差异svn diffgit diffgit diff
查看日志svn loggit loggit log 或 git svn log
添加文件svn add filegit add filegit add file
删除文件svn delete filegit rm filegit rm file
移动文件svn move old newgit mv old newgit mv old new
创建分支svn copy trunk branches/namegit branch namegit branch name (本地)
切换分支svn switch URLgit checkout branchgit checkout branch
合并分支svn merge URLgit merge branchgit merge branch
撤销修改svn revert filegit restore filegit restore file
忽略文件svn propset svn:ignore.gitignoregit svn show-ignore
查看信息svn info-git svn info
逐行追溯svn blame filegit blame filegit 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 推荐工作流

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 混合开发,从入门到精通!》 是转载文章,点击查看原文


相关推荐


Highcharts 双 Y 轴分组错位柱状图・代码详解
Highcharts.js2026/8/30

双 Y 轴、非分组错位并列柱状图,同时展示两类指标: 左轴:员工数量(人数,普通数值)右轴:利润(百万美元,金额) 同一分类下 4 根柱子错开摆放,不会互相重叠,用来对比「优化前 / 优化后」两组数据差异。 示例代码 Highcharts.chart('container', { chart: { type: 'column' }, title: { text: 'Efficiency Optimization by Branch


OpenCV实战——透视变换与身份证号码模板识别
clorinda2026/8/22

一、前言》》》》》》》 在现实生活中,发票、身份证和纸张通常不是完全正对着摄像头拍摄的。由于拍摄角度不同,原本的矩形会变成梯形,文字也会发生倾斜。 如果直接对这种图片进行识别,效果往往不理想。因此,通常需要先完成透视变换,把图像矫正成正面视图,再进行二值化、轮廓检测和模板匹配。 本篇主要介绍: 1,透视变换的原理; 2,四个角点的排序; 3,发票图像矫正; 4,形态学闭运算; 5,使用模板匹配识别身份证号码。 二、透视变换的基本原理 透视变换可以把原图中的任意四边形转换成一


Rust Borrow借用详解:不转移所有权访问数据
程序员爱钓鱼2026/8/9

《Rust编程实战》系列第35篇 在上一篇文章中,我们学习了Rust的Copy,了解了哪些轻量数据类型可以在赋值或传参时自动复制。本篇继续进入Rust所有权体系中非常重要的概念: Borrow 中文通常称为“借用”。 前面我们已经知道,String、Vec等非Copy类型传递给另一个变量或函数时,通常会发生所有权移动: fn print_name(name: String) { println!("{}", name); } fn main() { let name = S


Rust图像处理第22节-从RGB到YCbCr: 让亮度和颜色分家
花褪残红青杏小2026/7/31

🦀 Rust + WASM 实战系列 第 22 篇 阅读时间:约 8 分钟 | 实战可运行 📌 写在前面 前面 21 篇,所有图像都是拿 R、G、B 三个数表示的。这一篇换一套坐标系:一个亮度 + 两个色度。 手机里的每一张照片、你看的每一个视频,存进文件之前都会先做这个转换。原因很简单:人眼对亮度极其敏感,对颜色极其迟钝,把两者分开之后,颜色那部分可以随便砍。 数学上,它就是一个 3×3 矩阵(19节的矩阵 × 向量)加它的逆矩阵(21节的 try_inverse) 🚀 TL;DR


🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
ReBound2026/7/23

🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚! 摘要:Workflow 和 Agent 到底有啥区别?为什么 Coze 工作流和 ReAct Agent 看起来都在"执行任务",本质却完全不同?本文从面试翻车经历出发,结合 Anthropic 官方定义、ReAct 框架、完整代码示例和实战选型指南,帮你彻底搞懂这对最容易混淆的 AI 概念。 📌 前言 上周面试,面试官笑眯眯地问了一句: "你说说 AI Workflow 和 Agent


大模型入门:从“猜词游戏“到“超级大脑“,一篇读懂 AI 大模型
修己xj2026/7/15

2023 年初,ChatGPT 横空出世,"大模型"三个字一夜之间刷爆了所有人的朋友圈。有人拿它写代码,有人拿它写情书,还有人拿它辅导孩子做数学——而且它居然真的会。 可当你真正想搞懂"大模型到底是什么"时,迎面而来的却是满屏的"Transformer""自注意力""千亿参数",瞬间劝退。 别慌。这篇文章,我们用打比方的方式,把大模型从里到外讲清楚。 一、什么是大模型?先搞懂"大"在哪 今天大家口中的大模型,通常特指大语言模型(LLM,Large Language Model)。ChatGPT


【Java实习面试算法冲刺】双指针
ZenithSourceQuest2026/7/6

第2类题型:双指针 为什么双指针题看起来不难,你一到面试就容易写乱 很多同学第一次刷双指针时,会觉得这类题比哈希表还“直观”。因为代码通常不长,变量也常常只有 left、right、slow、fast 四个名字。但真正到了面试现场,双指针反而很容易暴露出两类问题: 你会套模板,但说不清两个指针各自代表什么。你知道要移动某一边,却解释不出“为什么这样移动不会漏解”。你能把 三数之和 写个大概,却总在去重和边界上翻车。你把“会写代码”当成“理解题型”,结果一换题面就不稳。 如果你


论虚拟线程与 Kotlin IO 协程:资源开销、时长、高并发表现及适用场景与技术选型思考
zimoyin2026/6/28

在现代并发编程中,虚拟线程(由 Java 20+ 引入)和 Kotlin IO 协程(基于 Dispatchers.IO)是两种高效处理异步任务的技术框架。在资源开销、时长(特别是长时间 IO)、高并发场景表现、以及何时选择合适方案等方面各有特点。本文将逐一展开对比分析。 1. 资源开销对比 虚拟线程和协程的核心开销差异源于其底层设计原理: 维度虚拟线程Kotlin IO 协程关键差异内存开销固定栈机制:默认约 1MB1\text{MB}1MB 占⽤[注1]动态内存分配:2KB∼512KB2


当 AI 学会「自己催自己」:对 Loop Engineering 的理解与思考
莫西很trouble2026/6/19

先说一个让我「咯噔」一下的瞬间 前段时间看到 Claude Code 负责人 Boris Cherny 说了句话,大意是:我已经不写 Prompt 了,我只写 Loop 我的第一反应是:啊?Prompt 不是刚学会怎么写好吗?怎么就又过时了? 但仔细想了下这句话背后的意思,突然意识到它不是在讲什么新技术,而是在讲一个我们早就该意识到的问题 ——如果每次用 AI,你都要在它身边喊「继续」「还是报错」「你改了啥」「回滚」,那说明你其实不是在用工具,你是在当监工 而 Loop Engineer


限流:从单机QPS计数器到分布式三层防御体系
程序员小策2026/6/11

大家好,我是程序员小策。 先说一个反直觉的事实:加了限流之后,你系统的成功请求数量反而可能变多。 听起来很荒诞对吧?限流的字面意思就是"拦住一部分请求",拦住了怎么可能变多? 但数据不会骗人: 场景总请求数成功数成功率不限流5000000%加了限流50000500010% 不限流的时候,50000 个请求全部涌入数据库,连接池打满,超时重试又制造了一倍流量,雪崩导致所有接口全部失败——包括那些只想来浏览商品页的正常用户。 加了限流之后,50000 个请求里被拦掉了 45000 个,但这

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读