SVN 是什么?
简单理解一下 SVN,SVN 是一个集中式版本控制系统,与 Git 等分布式系统不同,SVN 有一个中央服务器(仓库),所有开发者都从这个服务器上获取最新代码(checkout),并将自己的修改提交(commit)到服务器。

核心概念
在开始使用命令前,了解这几个核心概念很重要:
- 仓库: 存放所有项目文件和版本历史记录的中央服务器地址。
svn://server_ip/project_repo或http://server_ip/project_repo。 - 工作副本: 你从仓库中
checkout到本地机器的文件目录,这是你进行日常编辑的地方。 - 修订版本: 每次提交都会产生一个新的修订版本号,从 1 开始递增,这可以精确定位到任何一个历史状态。
- 状态: 文件或目录的当前状态,通常是:
修改: 文件在工作副本中被修改了,但未提交。已添加: 文件被标记为添加,但还未提交。已删除: 文件被标记为删除,但还未提交。冲突: 你的修改和其他人的修改发生了冲突,需要手动解决。正常: 文件未被修改,与仓库中的版本一致。
常用基础命令
这些是日常使用频率最高的命令。
svn checkout (或 svn co)
作用: 从仓库下载一个项目到本地,创建工作副本。
语法: svn checkout [仓库URL] [本地目录路径]
示例:

# 从仓库检出项目到当前目录下的 my_project 文件夹 svn checkout svn://example.com/project_repo my_project # 如果只检出项目主干,并希望只获取最新版本(不下载历史记录) svn checkout svn://example.com/project_repo/trunk my_project --depth empty
svn update (或 svn up)
作用: 从仓库拉取最新的代码,更新你的工作副本,这是协作开发中最常用的命令之一。
语法: svn update [本地目录路径]
示例:
# 更新当前目录及其所有子目录 svn update # 更新到指定的修订版本号 svn update -r 100 # 只更新当前目录,不递归更新子目录 svn update --depth immediates
svn commit (或 svn ci)
作用: 将你在本地工作副本中的修改(添加、删除、修改文件)提交到中央仓库。
语法: svn commit [本地目录路径] -m "提交日志"
关键点:

- 必须带
-m参数,并提供清晰的提交日志,说明这次修改的内容。 - 提交前,最好先用
svn status检查一下要提交的内容。
示例:
# 提交当前目录下的所有修改 svn commit -m "修复了用户登录按钮无法点击的 bug" # 提交指定文件的修改 svn commit src/login.js -m "优化了登录逻辑"
svn status (或 svn st)
作用: 查看工作副本中文件的修改状态,这是你执行 commit 前的必做步骤。
语法: svn status [本地目录路径]
常用状态码:
- ` ` (空格): 文件未修改。
M: 文件被修改了。A: 文件被标记为添加。D: 文件被标记为删除。C: 文件发生冲突。- 文件未被 SVN 控制(未
add)。 - 文件丢失或不在 SVN 控制下。
示例:
svn status # 输出示例: # M index.html # A new_feature.js # ? temp_file.txt # D old_feature.js
svn add
作用: 将一个新文件或新目录纳入 SVN 的版本控制,标记为“已添加”,执行 add 后,文件仍然存在于本地,需要执行 commit 才会上传到仓库。
语法: svn add [文件或目录路径]
示例:
# 添加单个新文件 svn add style.css # 添加一个新目录及其下所有未控制的文件 svn add assets/
svn delete (或 svn rm)
作用: 从版本控制中删除文件或目录,这同样是一个“标记”操作,需要 commit 才能生效。
语法: svn delete [文件或目录路径]
示例:
# 删除一个文件 svn delete unused_file.js # 删除一个目录 svn delete old_folder/
查看与比较命令
svn log
作用: 查看项目的提交历史记录。
语法: svn log [本地目录路径或文件路径]
常用选项:
-v: 显示每次修改涉及的文件列表(非常常用)。-l N: 只显示最新的 N 条记录。
示例:
# 查看当前目录的提交历史 svn log # 查看提交历史,并显示每次修改的文件 svn log -v # 查看最新的 5 条提交历史 svn log -l 5
svn diff
作用: 比较文件在工作副本中的修改与仓库中最新版本的差异。
语法: svn diff [文件路径]
示例:
# 比较当前修改的文件 svn diff index.html # 比较两个不同修订版本之间的差异 svn diff -r 90:100 index.html
svn blame (或 svn annotate)
作用: 显示每一行代码的最后修改者和修订版本号。
语法: svn blame [文件路径]
示例:
# 查看 utils.js 每行代码的作者和版本 svn blame src/utils.js
分支与标签管理
SVN 的分支和标签是通过在仓库中创建特殊目录来实现的。
svn copy
作用: 创建分支或标签,它是一个“立即”操作,会创建一个新的修订版本。
语法: svn copy [源URL] [目标URL] -m "创建分支/标签的日志"
示例:
假设仓库结构为 svn://example.com/project_repo/trunk (主干) 和 svn://example.com/project_repo/branches (分支目录)。
# 从主干创建一个名为 feature-x 的新分支
svn copy svn://example.com/project_repo/trunk \
svn://example.com/project_repo/branches/feature-x \
-m "创建 feature-x 分支开发新功能"
# 创建一个名为 v1.0 的标签
svn copy svn://example.com/project_repo/trunk \
svn://example.com/project_repo/tags/v1.0 \
-m "发布 v1.0 版本"
svn switch
作用: 将你的工作副本从一个 URL(如主干)切换到另一个 URL(如分支),这是在分支间切换工作的核心命令。
语法: svn switch [新URL] [本地目录路径]
示例:
# 假设你在主干目录下,现在要切换到 feature-x 分支 svn switch svn://example.com/project_repo/branches/feature-x . # 切换回主干 svn switch svn://example.com/project_repo/trunk .
svn merge
作用: 合并一个分支的修改到另一个分支(通常是主干),这是 SVN 合并代码的主要方式。
语法: svn merge [源URL1@版本1] [源URL2@版本2] [本地目录路径]
示例:
假设你在主干上工作,现在要把 feature-x 分支的所有修改合并过来。
# 1. 首先在 feature-x 分支上,找到它的创建版本号 (比如是 101) # svn log -v svn://example.com/project_repo/branches/feature-x | head # 2. 切换回主干目录 # svn switch svn://example.com/project_repo/trunk . # 3. 执行合并,将版本 101 之后的 feature-x 分支的所有变更合并到当前主干目录 svn merge -r 101:HEAD svn://example.com/project_repo/branches/feature-x . # 4. 检查合并结果,如果没有冲突,就提交 svn commit -m "合并 feature-x 分支的代码到主干"
冲突解决
当多人修改了同一文件的同一行时,就会发生冲突。
- 发生冲突:
svn status会显示C标记。 - 查看冲突:
svn diff可以看到冲突的具体内容。 - 解决冲突: 手动打开冲突的文件,SVN 会在文件中用
<<<<<<< .mine, ,>>>>>>> .r123这样的标记标出冲突部分,你需要编辑文件,删除这些标记,并保留正确的代码。 - 标记冲突已解决: 解决完后,运行
svn resolved [文件路径],这会移除冲突状态。 - 提交:
commit你的解决。
# 1. 更新代码,发现冲突 svn update # index.html # C index.html # 2. 手动编辑 index.html,解决冲突 # 3. 标记冲突已解决 svn resolved index.html # 4. 提交解决结果 svn commit -m "解决了 index.html 的合并冲突"
最佳实践与提示
-
先
update,再commit: 在提交你的代码之前,务必先update,确保你是在最新的代码基础上进行修改,避免不必要的冲突。 -
写清晰的提交日志:
-m后面的日志信息要简洁明了,说明你做了什么,解决了什么问题,这方便自己和他人回顾历史。 -
善用
status: 在执行任何可能改变文件状态的操作(add,delete,commit)前,先用status检查一下,做到心中有数。 -
不要在
.svn目录里乱动:.svn目录是 SVN 的工作区元数据,不要手动修改或删除它。 -
忽略文件: 对于一些不需要版本控制的文件(如日志、编译产物、IDE 配置文件),应该创建一个
svn:ignore属性,在工作副本的根目录下执行:# 设置忽略所有 .log 文件 svn propset svn:ignore "*.log" . # 设置忽略一个名为 build 的目录 svn propset svn:ignore "build" .
从 SVN 迁移到 Git
SVN 已经逐渐被 Git 所取代,如果你或你的团队正在考虑迁移,可以了解一下 Git 相对于 SVN 的优势:
- 分布式: 每个开发者都有完整的代码仓库,离线工作能力强。
- 分支管理: Git 的分支创建、切换和合并非常快速和方便。
- 性能: 大多数 Git 操作都是本地操作,速度远快于需要联网的 SVN。
SVN 仍然在一些遗留项目中使用,掌握这些命令对于维护旧项目依然非常有用,但对于新项目,强烈推荐使用 Git。
