SVN 教程

SVN 教程

SVN(Subversion)是一款集中式版本控制系统,由 Apache 基金会维护,广泛用于软件开发中的代码版本管理。虽然 Git 已成为主流,但 SVN 在企业存量项目中仍有大量应用。

SVN 核心概念

  • 仓库(Repository):集中存放所有版本数据的服务器
  • 工作副本(Working Copy):本地检出的代码目录
  • 检出(Checkout):从仓库获取代码到本地
  • 提交(Commit):把本地修改上传到仓库
  • 更新(Update):把仓库最新代码同步到本地
  • 版本(Revision):每次提交生成唯一版本号

集中式 vs 分布式

特性SVN(集中式)Git(分布式)
仓库位置唯一中央仓库每台机器完整副本
离线提交不可以可以
分支成本较高低
适用场景企业内网、传统项目开源、分布式协作

基本工作流

svn checkout url            # 检出
# 修改文件...
svn add 新文件              # 添加新文件
svn commit -m "说明"        # 提交
svn update                 # 更新(拉取他人修改)

SVN 简介

SVN 简介

1. 历史

Subversion 由 CollabNet 于 2000 年发起,旨在替代老旧的 CVS。2009 年成为 Apache 基金会顶级项目,是目前最流行的集中式版本控制系统。

2. 核心特性

  • 集中管理:所有版本历史存于中央仓库,权限统一控制
  • 原子提交:一次提交要么全部成功要么全部失败
  • 目录版本化:目录本身也是版本化对象,支持移动/复制/删除
  • 二进制支持:可管理图片、文档等二进制文件
  • 廉价复制:分支与标签通过复制实现,成本低

3. 目录结构

SVN 仓库通常遵循标准目录结构:

仓库根/
├── trunk/       主开发线(主干)
├── branches/    分支(功能/发布/修复)
└── tags/        标签(发布快照)

4. 常见客户端

  • TortoiseSVN:Windows 资源管理器集成,最流行
  • 命令行 svn:跨平台,脚本友好
  • IDEA/Eclipse 插件:IDE 内置
  • Cornerstone:macOS 图形客户端

5. 与其他工具集成

  • Bug 追踪系统(Jira、Redmine)
  • CI/CD(Jenkins、GitLab CI 支持 SVN)
  • 代码评审工具

SVN 安装

SVN 安装

1. 服务器端安装

# Ubuntu/Debian
sudo apt install subversion

# CentOS
sudo yum install subversion

# 验证
svn --version

# Windows 服务器
# 下载 VisualSVN Server(集成界面)或 CollabNet

2. 创建仓库

# 创建仓库目录
svnadmin create /opt/svn/repos

# 创建标准结构
svn mkdir -m "创建标准目录"     file:///opt/svn/repos/trunk     file:///opt/svn/repos/branches     file:///opt/svn/repos/tags

3. 启动服务

# 方式一:svnserve(独立守护进程)
svnserve -d -r /opt/svn
# 访问: svn://host/repos

# 方式二:Apache 集成(支持 HTTP/HTTPS)
# 安装 mod_dav_svn 并配置

# 方式三:SSH 隧道
svn+ssh://user@host/opt/svn/repos

4. 客户端安装

# Linux/macOS
sudo apt install subversion    # Ubuntu
brew install subversion        # macOS

# Windows
# 命令行:下载 SlikSVN 或 VisualSVN
# 图形:安装 TortoiseSVN

# 验证
svn --version

5. 配置访问控制

# 编辑 conf/svnserve.conf
[general]
anon-access = none        # 匿名禁止
auth-access = write       # 认证可写
password-db = passwd      # 用户密码文件
authz-db = authz          # 权限文件

# conf/passwd 添加用户
[users]
zhangsan = password123
lisi = password456

# conf/authz 配置权限
[/]
zhangsan = rw
lisi = r
* =

SVN 生命周期

SVN 生命周期

理解 SVN 的工作流程,是使用好版本控制的关键。

1. 核心状态

仓库(Repository)     中央数据存储
检出(Checkout)       创建工作副本
更新(Update)         同步仓库最新状态
修改(Edit)           本地编辑文件
添加/删除(Add/Delete) 变更文件集合
提交(Commit)         变更写入仓库
回退(Revert)         撤销本地修改

2. 创建与检出

# 创建仓库
svnadmin create repos

# 检出到工作目录
svn checkout svn://localhost/repos/trunk myproject
# 或
svn co svn://host/repos/trunk myproject

3. 日常修改循环

# 1. 更新到最新
svn update

# 2. 修改代码、添加新文件
svn add newfile.py
svn add *.txt

# 3. 查看状态与差异
svn status
svn diff

# 4. 提交
svn commit -m "实现登录功能"
# 或简写
svn ci -m "说明"

4. 冲突处理

# 提交前先更新,发现冲突
svn update
# 输出: C file.txt(冲突)

# 查看冲突文件
svn resolve file.txt --accept mine-conflict
# 或手动编辑后标记解决
svn resolve file.txt

# 提交解决后的文件
svn commit -m "解决冲突"

5. 生命周期最佳实践

  • 每次提交前先 svn update
  • 提交信息写清楚改动内容
  • 小步提交,避免一次性大量变更
  • 不要提交编译产物和临时文件
  • 设置 svn:ignore 忽略无用文件

SVN 启动模式

SVN 启动模式

SVN 服务可以通过多种方式启动,适应不同的网络环境。

1. svnserve 模式(独立服务)

# 启动守护进程,默认端口 3690
svnserve -d -r /opt/svn

# 参数说明
-d  后台守护进程模式
-r  指定仓库根目录
--listen-port 3690   指定端口
--listen-host 0.0.0.0 绑定地址

# 访问方式
svn://host/repos
svn://host/repos/trunk

2. Apache HTTP 模式

# 安装模块
sudo apt install libapache2-mod-svn

# 配置 /etc/apache2/mods-available/dav_svn.conf
<Location /svn>
    DAV svn
    SVNParentPath /opt/svn
    AuthType Basic
    AuthName "SVN Repository"
    AuthUserFile /etc/apache2/dav_svn.passwd
    Require valid-user
</Location>

# 创建用户
htpasswd -c /etc/apache2/dav_svn.passwd zhangsan

# 重启 Apache
sudo systemctl restart apache2

# 访问方式(支持 Web 浏览)
http://host/svn/repos
https://host/svn/repos

3. SSH 隧道模式

# 通过 SSH 访问
svn+ssh://user@host/opt/svn/repos

# 配置 ssh 免密(可选)
ssh-keygen
ssh-copy-id user@host

4. 模式对比

模式端口安全适用
svnserve3690明文,可配 SSL内网小团队
Apache80/443HTTPS 加密跨网络、需 Web 浏览
SSH22SSH 加密已有 SSH 环境

5. 防火墙与安全

# 开放端口
sudo ufw allow 3690/tcp    # svnserve
sudo ufw allow 443/tcp     # HTTPS

# 备份仓库
svnadmin hotcopy /opt/svn/repos /backup/repos-$(date +%F)
# 定期备份 + 增量备份

SVN 创建版本库

SVN 创建版本库

1. 创建仓库

# 创建目录
mkdir -p /opt/svn
cd /opt/svn

# 创建版本库
svnadmin create repos

# 查看结构
ls repos
# conf  db  format  hooks  locks  README.txt

2. 初始化标准结构

# 通过文件协议创建标准目录
svn mkdir -m "初始化"     file:///opt/svn/repos/trunk     file:///opt/svn/repos/branches     file:///opt/svn/repos/tags

# 或用导入方式
mkdir -p /tmp/project/trunk
echo "hello" > /tmp/project/trunk/readme.txt
svn import /tmp/project file:///opt/svn/repos -m "导入项目"

3. 配置文件

# repos/conf/svnserve.conf
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
realm = MyRepository

# repos/conf/passwd
[users]
admin = admin123
dev1 = dev123
dev2 = dev456

# repos/conf/authz(示例)
[groups]
devteam = dev1, dev2

[/]
admin = rw

[repos:/trunk]
@devteam = rw

[repos:/branches]
dev1 = rw
* = r

4. 启动与验证

# 启动服务
svnserve -d -r /opt/svn

# 客户端验证
svn list svn://localhost/repos

# 检出测试
svn co svn://localhost/repos/trunk test-wc

5. 仓库维护

# 查看仓库信息
svnadmin info /opt/svn/repos

# 校验完整性
svnadmin verify /opt/svn/repos

# 备份
svnadmin dump /opt/svn/repos > repos.dump
# 恢复
svnadmin load /opt/svn/newrepos < repos.dump

# 热拷贝备份(推荐,不停服)
svnadmin hotcopy /opt/svn/repos /backup/repos

# 升级格式
svnadmin upgrade /opt/svn/repos

SVN 检出操作

SVN 检出操作

1. 基本检出

# 检出整个 trunk
svn checkout svn://host/repos/trunk myproject

# 简写 co
svn co svn://host/repos/trunk

# 检出到指定目录
svn co svn://host/repos/trunk /home/user/project

# 检出指定版本
svn co svn://host/repos/trunk -r 100 project

# 检出到当前目录(加 .)
svn co svn://host/repos/trunk .

2. 检出指定目录

# 只检出 src 子目录(稀疏检出)
svn co svn://host/repos/trunk/src src

# 浅检出(不拉取历史)
svn co --depth empty svn://host/repos/trunk
svn update --set-depth infinity   # 之后补全

3. 工作副本状态

# 查看状态
svn status
# 输出解读:
# A  新增  M 修改  D 删除
# C  冲突  ? 未纳入  ! 缺失

# 查看文件详情
svn info
svn info file.txt
# URL、Revision、Last Changed 等

# 查看仓库目录
svn list svn://host/repos/trunk
svn ls svn://host/repos

4. 更新操作

# 更新工作副本到最新
svn update

# 更新到指定版本
svn update -r 50

# 更新单个文件
svn update file.txt

# 更新时忽略冲突提示
svn update --accept theirs-full

5. 检出问题排查

# 认证失败
# 检查用户名密码,或添加 --username --password

# 权限不足
# 检查 authz 配置

# 网络不通
svn ls svn://host/repos  # 测试连通

# 清缓存重试
rm -rf ~/.subversion/auth

SVN 解决冲突

SVN 解决冲突

多人同时修改同一文件时会产生冲突,需要手动解决。

1. 冲突的产生

# 场景:
# 你和同事都修改了 file.txt 的同一行
# 你先提交,同事 update 时产生冲突

# 冲突输出
C file.txt
# 冲突标记: C 表示冲突(Conflicted)

2. 冲突文件

# 冲突后生成三个文件
file.txt            # 冲突合并版本(需手动解决)
file.txt.mine       # 你的版本
file.txt.r100       # 冲突前的仓库版本(100)
file.txt.r102       # 最新仓库版本(102)

# 冲突标记内容
<<<<<<< .mine
我的修改内容
=======
别人的修改内容
>>>>>>> .r102

3. 解决方式

# 方式一:保留我的版本
svn resolve file.txt --accept mine-full
# 或 mine-conflict(仅冲突处用我的)

# 方式二:保留对方版本
svn resolve file.txt --accept theirs-full

# 方式三:手动编辑后标记解决
# 编辑 file.txt 保留期望内容
svn resolve file.txt --accept working

# 简写标记已解决
svn resolved file.txt

4. 冲突预防

# 1. 提交前先更新
svn update

# 2. 及时提交,减少冲突窗口

# 3. 避免同时修改同一模块

# 4. 用锁定(Lock)保护关键文件
svn lock file.txt        # 加锁
svn unlock file.txt      # 解锁
# 加锁后他人提交会失败,适合二进制文件

5. 冲突处理流程

1. svn update 发现冲突
2. 查看冲突文件内容
3. 与同事沟通合并策略
4. 编辑文件保留最终内容
5. svn resolve --accept working
6. 测试后提交
7. 提交信息注明冲突解决

SVN 提交操作

SVN 提交操作

1. 基本提交

# 提交所有修改
svn commit -m "修复登录 Bug"

# 提交指定文件
svn commit file1.py file2.py -m "修改配置"

# 简写 ci
svn ci -m "提交说明"

# 不带 -m 会打开编辑器(默认 vim)
svn commit

2. 提交前检查

# 查看修改内容
svn status        # 文件状态
svn diff          # 具体差异
svn diff file.py  # 单文件差异

# 撤销本地修改(不想要了)
svn revert file.py        # 单文件
svn revert -R .           # 递归全部

# 添加新文件
svn add newfile.txt
svn add *.py

# 删除文件
svn delete old.py
# 或直接 svn rm old.py

3. 提交信息规范

# 好的提交信息
svn ci -m "修复:用户登录时密码加密传输"
svn ci -m "新增:导出 Excel 报表功能"
svn ci -m "重构:抽取数据库连接工具类"

# 不好的信息
svn ci -m "改了一下"
svn ci -m "aaa"

# 建议格式:类型 + 简述
# fix: / feat: / docs: / refactor: / test:

4. 提交后操作

# 查看提交日志
svn log
svn log -l 10          # 最近 10 条
svn log file.py        # 文件历史
svn log -v             # 详细(含变更文件)
svn log -r 100:110     # 版本区间

# 查看版本详情
svn info
svn info -r 105

5. 提交最佳实践

  • 提交前 update,先解决冲突
  • 小步提交,逻辑完整即可提交
  • 不要提交编译产物(.class、node_modules、__pycache__)
  • 设置 svn:ignore 忽略无用文件
  • 提交信息描述"为什么"而非"改了什么"

SVN 版本回退

SVN 版本回退

1. 查看历史版本

# 查看提交日志
svn log
svn log -r 100:105

# 查看某版本的文件内容
svn cat -r 100 file.txt

# 查看文件版本差异
svn diff -r 100:105 file.txt

# 查看仓库目录在指定版本的结构
svn list -r 100 svn://host/repos/trunk

2. 更新到旧版本(查看)

# 整个工作副本回到旧版本
svn update -r 100

# 单个文件回到旧版本
svn update -r 100 file.txt

# 注意:这会"倒退"你的工作副本
# 之后提交需谨慎

3. 回退提交(reverse-merge)

# 撤销某次提交(推荐方式)
# 例如撤销版本 105 的修改
svn merge -c -105 .
svn commit -m "回退 105 的修改"

# 撤销一段版本区间
svn merge -r 110:105 .   # 撤销 105-110 的提交
svn commit -m "回退 105 到 110"

# 先看将要产生的变化
svn merge -c -105 --dry-run .

4. 恢复误删文件

# 误删文件后从仓库恢复
svn copy svn://host/repos/trunk/file.txt file.txt
svn commit -m "恢复误删的 file.txt"

# 或者:
svn revert file.txt     # 未提交的删除可还原
svn update file.txt     # 已提交的删除,update 可拉回?

5. 回退注意事项

  • 用 merge 回退而非直接 update -r(会丢失工作副本)
  • 回退前备份工作副本
  • 回退本身也是一次提交,写好说明
  • 回退后通知团队同步更新

SVN 查看历史信息

SVN 查看历史信息

1. svn log 日志

# 基本日志
svn log

# 限制条数
svn log -l 20

# 指定版本区间
svn log -r 90:100

# 详细日志(显示变更文件)
svn log -v

# 显示差异
svn log -d

# 单文件历史
svn log file.txt

# 指定时间范围
svn log -r {2026-01-01}:{2026-08-18}

2. svn diff 差异

# 本地未提交修改
svn diff

# 单文件
svn diff file.py

# 与指定版本对比
svn diff -r 100 file.py

# 两个版本间对比
svn diff -r 100:110

# 仓库版本对比
svn diff -r 100 svn://host/repos/trunk/file.py

3. svn blame 追溯

# 逐行显示最后修改人和版本
svn blame file.py
# 输出: 105 zhangsan  登录逻辑
#       108 lisi      bug修复

# 别名 annotate / praise
svn annotate file.py

# 指定版本
svn blame -r 100 file.py

4. svn info 信息

svn info
# Path、URL、Repository Root、Revision
# Last Changed Rev/Date/Author

svn info file.txt
svn info -r 100

5. 历史分析场景

# 找某行是谁改的
svn blame file.py | grep "关键代码"

# 看某功能何时引入
svn log -v | grep -B5 "feature"

# 对比发布版本差异
svn diff -r {tag_v1.0}:{tag_v2.0} --summarize

# 统计提交量
svn log | grep -c "^r"

SVN 分支

SVN 分支

分支用于并行开发互不干扰的功能,完成后再合并回主干。

1. 创建分支

# 从 trunk 复制创建分支(推荐用 svn copy)
svn copy svn://host/repos/trunk          svn://host/repos/branches/feature-login          -m "创建登录功能分支"

# 或者基于指定版本
svn copy svn://host/repos/trunk@100          svn://host/repos/branches/release-2.0          -m "基于 r100 创建 2.0 发布分支"

2. 切换到分支

# 检出分支(新工作副本)
svn co svn://host/repos/branches/feature-login

# 已有工作副本切换分支
svn switch svn://host/repos/branches/feature-login

# 切换回主干
svn switch svn://host/repos/trunk

# 查看当前分支
svn info | grep URL

3. 合并分支回主干

# 1. 切到主干
svn switch svn://host/repos/trunk

# 2. 更新到最新
svn update

# 3. 合并分支(计算从创建点以来的所有变更)
svn merge svn://host/repos/branches/feature-login

# 4. 解决冲突(如有)
svn status
# 手动解决冲突后
svn resolve --accept working conflicted-file

# 5. 测试后提交
svn commit -m "合并登录功能分支到主干"

4. 合并指定区间

# 合并分支的 110-120 版本
svn merge -r 110:120 svn://host/repos/branches/feature-login

# 查看合并预览
svn merge --dry-run -r 110:120 svn://host/repos/branches/feature-login
svn diff

5. 分支管理最佳实践

  • 标准结构:trunk 主干 + branches 功能分支 + tags 标签
  • 功能分支命名:feature-xxx / bugfix-xxx
  • 发布分支:release-x.y
  • 分支合并前先同步主干到分支(svn merge trunk)
  • 定期合并,避免分支过老

SVN 标签

SVN 标签

标签(tag)是某一时刻代码的快照,通常用于标记发布版本,创建后不再修改。

1. 创建标签

# 从主干创建标签
svn copy svn://host/repos/trunk          svn://host/repos/tags/v2.0.0          -m "发布 v2.0.0"

# 从指定版本创建
svn copy svn://host/repos/trunk@150          svn://host/repos/tags/v1.5.0          -m "基于 r150 打标签"

# 从分支创建
svn copy svn://host/repos/branches/release-2.0          svn://host/repos/tags/v2.0.1          -m "发布补丁版本"

2. 查看与切换标签

# 查看所有标签
svn list svn://host/repos/tags

# 检出某个标签(只读)
svn co svn://host/repos/tags/v2.0.0 release-2.0.0

# 查看标签内容
svn ls svn://host/repos/tags/v2.0.0

3. 标签规范

# 语义化版本号
v1.0.0  v1.1.0  v2.0.0

# 版本号规则
主版本.次版本.补丁
v2.0.0-alpha   预发布
v2.0.0-rc1     候选发布

# 命名建议
release-1.0.0
v1.0.0
2016-08-18(日期式,不推荐)

4. 基于标签修复

# 1. 从标签建修复分支
svn copy svn://host/repos/tags/v2.0.0          svn://host/repos/branches/hotfix-2.0.1          -m "2.0.1 修复分支"

# 2. 在分支修复并提交
svn co svn://host/repos/branches/hotfix-2.0.1
# 修改文件...
svn commit -m "修复紧急 Bug"

# 3. 重新打标签
svn copy svn://host/repos/branches/hotfix-2.0.1          svn://host/repos/tags/v2.0.1          -m "发布 v2.0.1"

# 4. 合并修复回主干
svn switch svn://host/repos/trunk
svn merge svn://host/repos/branches/hotfix-2.0.1
svn commit -m "合并 2.0.1 修复"

5. 标签最佳实践

  • 标签一旦创建不再修改(如需修改则建新标签)
  • 发布版本必须打标签,便于回溯
  • 标签目录保持整洁,语义清晰
  • CI/CD 可从标签构建发布

TortoiseSVN 使用教程

TortoiseSVN 使用教程

TortoiseSVN 是 Windows 上最流行的 SVN 图形客户端,集成在资源管理器中,右键即可完成所有操作。

1. 安装

# 从 tortoisesvn.net 下载安装包
# 安装时选择语言包(中文)
# 安装后右键菜单出现 SVN 相关选项

2. 检出(Checkout)

1. 新建文件夹,进入
2. 右键 → SVN Checkout...
3. URL of repository: 填入 svn://host/repos/trunk
4. Checkout directory: 自动填当前目录
5. 点击 OK

# 图标说明
绿色对勾: 与仓库一致
红色感叹号: 有本地修改
黄色警告: 有冲突
蓝色加号: 新文件未添加

3. 提交(Commit)

1. 修改文件后,在文件夹右键 → SVN Commit...
2. 勾选要提交的文件
3. 填写提交信息(Message)
4. 点击 OK

# 右键单文件也可直接提交

4. 更新(Update)

# 右键 → SVN Update
# 获取最新代码

# 更新到指定版本
# 右键 → TortoiseSVN → Update to Revision...

5. 常用操作

# 查看修改
右键 → SVN Show log      # 提交历史
右键 → TortoiseSVN → Check for modifications  # 本地修改
右键 → TortoiseSVN → Diff  # 查看差异

# 添加/删除
右键 → TortoiseSVN → Add        # 添加新文件
右键 → TortoiseSVN → Delete      # 删除

# 分支与标签
右键 → TortoiseSVN → Branch/Tag
# 复制到 branches/xxx 或 tags/v1.0

# 合并
右键 → TortoiseSVN → Merge...

6. 冲突解决界面

# 冲突时 TortoiseSVN 提供图形化合并工具
# Edit Conflicts 打开 3 窗口对比
# 可逐块选择"使用我的"或"使用对方的"

# 或者右键 → TortoiseSVN → Edit conflicts
# 完成后 → Mark as resolved

7. 常用设置

# 右键 → TortoiseSVN → Settings
# Global ignore pattern: 忽略文件模式
# *.class *.log node_modules/ __pycache__/

# 自动添加 svn:ignore
# 右键 → TortoiseSVN → Properties
# 添加 svn:ignore 属性

# 认证缓存
# 首次连接保存用户名密码
第 1 / 14 节