TortoiseSVN 是 Windows 上最主流的 Subversion 客户端,装完之后它就以资源管理器右键菜单的形式存在,没有独立的窗口。它的上手门槛很低——右键、提交、更新,三步就能干活——但真正会卡住人的往往不是命令本身,而是几个和 Windows 贴太近的地方:图标覆盖不显示、命令行工具默认没装、工作副本的内部结构变了、忽略文件配了三层却不知道哪层生效。
这篇按实际使用的顺序捋一遍:装之前要注意什么、图标不显示怎么修、日常操作里哪几个最容易被用错、忽略/锁/分支/冲突怎么配,最后是命令行的用法和一份避坑清单。
一、安装:三个默认设置会坑到你
TortoiseSVN 的当前版本是 1.14.9(LTS,内置 Subversion 1.14.5 库),提供 32 位、64 位和 ARM64 三种安装包,按系统架构选即可。
系统要求这一项要先看清楚,1.14 起最低要求 Windows 10(底层需要 Windows 10 1607 引入的 SetThreadDpiAwarenessContext(),安装程序会直接检测并拒绝安装)。老系统只能退版本:
| 操作系统 | 能用的 TortoiseSVN |
|---|---|
| Windows 10 / 11 | 1.14.x(当前 LTS,推荐) |
| Windows 8.1 | 1.13 及更早 |
| Windows 7 / 8 | 1.10 |
| Windows Vista | 1.9 |
| Windows XP | 1.8 |
顺带一提,深色模式只在 Windows 10 1809 及以上才能启用,老一点的 Win10 版本只能继续用浅色主题。
坑 1:命令行客户端默认不装
安装向导走到 Command line client tools 这一步时,默认选项是 will not be installed。也就是说你装完 TortoiseSVN,在命令行敲 svn 依然是「不是内部或外部命令」。
如果你要用脚本、要跑钩子、要在 CI 或别的工具里调 svn,这一步必须手动改成安装。事后补救的办法是重新运行安装包选 Modify 补上,不用卸载重装。
坑 2:64 位系统上的 32 位程序
在 64 位 Windows 上,TortoiseSVN 的右键菜单和图标覆盖默认只在 64 位程序里出现。如果你需要在 32 位应用(一些老 IDE、老工具)的文件对话框里也用上,得额外装一份 vc_redist.x86.exe(2022 C 运行时)。这个不影响资源管理器本身,只影响那些 32 位宿主程序。
坑 3:装完没生效
shell 扩展是随资源管理器进程加载的,装完不重启资源管理器通常看不到变化。重启一次机器最省事,只想快点的话在任务管理器里重启「Windows 资源管理器」也行。
另外要纠正一个常见的期望偏差:TortoiseSVN 只是资源管理器扩展,不是 IDE 插件。它不会出现在 Visual Studio 的菜单里,VS 里要集成 SVN 得另装商业插件 VisualSVN。至于服务端,那是另一套东西——VisualSVN Server 或者原版 svnserve / Apache,和客户端版本不必严格对齐,但客户端版本低于服务端太多时可能读不了新格式的仓库数据。
二、图标覆盖不显示:Windows 只有 11 个槽位
这是 TortoiseSVN 被问得最多的问题,而且它的根因不在 TortoiseSVN,在 Windows。
资源管理器的图标覆盖(就是文件左下角那个绿色对勾、红色感叹号)在系统里是全局共享的有限资源:Windows 最多认 15 个覆盖图标,其中资源管理器自己要用掉几个,真正留给第三方应用的只剩大约 11 个。而注册了覆盖图标的软件远不止一家——OneDrive、Dropbox、坚果云、各类网盘、Git 客户端、杀毒软件都会来抢。
更要命的是分配规则:这些处理程序按注册表键名的 ASCII 字母顺序取前 11 个,排在后面的直接被忽略。有些软件(OneDrive 是典型)会故意在键名前加一个空格,而空格在 ASCII 里排在所有字母前面,于是它永远抢到位置,TortoiseSVN 就被挤出去了。注册表位置:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers
打开 regedit.exe(管理员权限)就能看到这场排位赛:谁排在前 11 名,谁才能显示。
正确的修法:先用 TortoiseSVN 自带的界面
右键任意位置 → TortoiseSVN → Settings → Icon Overlays → Overlay Handlers,这里有一个带复选框的处理程序列表,可以先全部取消勾选并应用,再重新勾上你需要的几项并应用。这个动作会让 TortoiseSVN 把自己的注册表键重新排序到前面,多数情况到这一步就修好了,不用手动动注册表。
做完重启资源管理器(或 F5)看效果。
还不行再动注册表
如果重排之后仍然不显示——通常是抢位子的程序太多,或者有程序用了带前导空格的键名——才需要手工调整:
- 先导出备份:右键
ShellIconOverlayIdentifiers项 → 导出,存一份.reg。 - 把 Tortoise 往前挪:给
1TortoiseNormal、2TortoiseModified这类键名前再加一些空格,让它们排到更前面。 - 把用不上的往后压:给网盘、其他客户端的键名前加
z,让它们沉底。 - 重启资源管理器。
两个注意点:被保护的程序(OneDrive 就是)改名前要先取得该项的所有权并给当前用户完全控制权限;另外实践下来「只重命名 TortoiseSVN 自己」有时不够,需要把整个列表压到 11 个以内才生效。
另一种「不显示」,其实不是抢位子
| 现象 | 真正的原因 | 处理 |
|---|---|---|
| 网络盘、映射盘、虚拟机共享目录里的文件没有图标 | 默认不对网络驱动器做覆盖 | Settings → Icon Overlays → Drive Types 里勾上 Network drives |
| 大工作副本下光标转圈、磁盘狂读 | 状态缓存默认递归扫描整个工作副本 | Settings → Icon Overlays → Status cache 从 Default 改为 Shell(代价是状态可能滞后,F5 刷新) |
| 只有根目录有图标,子目录没有 | 被设成了非递归状态显示 | Settings → Icon Overlays 里确认状态显示方式是递归的 |
| 图标显示成灰色的问号/感叹号 | tsvncache 还没算完,或者工作副本被别处动过 | 在根目录右键 → Clean up 修时间戳 |
三、日常操作:三个最容易被用错的命令
右键菜单里的常规项(Checkout、Update、Commit、Show log、Repo-browser、Blame、Revision graph)基本看一眼就懂,这里只说三个语义容易被混淆、出错代价也比较大的。
1. Update to revision ≠ Switch
| Update to revision | Switch | |
|---|---|---|
| 目的 | 把工作副本退回到某个历史版本看代码 | 把工作副本换到另一个分支/标签的 URL 上 |
| 工作副本的 URL | 不变 | 改成新 URL 并记录在 .svn 里 |
| 后续影响 | 是「粘性」的:之后 Update 默认还停在那个版本上,必须再 Update to HEAD 才回来 | 一直停在新分支上,直到你再 Switch 回去 |
最常见的翻车是:为了看一眼历史版本点了 Update to revision,然后忘了切回 HEAD,改了代码发现提交不上去(工作副本处于旧版本,提交会报 out of date)。只想看历史代码的话,其实用 Show log → 右键某个版本 → 打开文件,或者干脆 Repo-browser 更安全,完全不污染工作副本。
2. Revert 和「Revert changes from this revision」是两回事
- Revert(右键 → TortoiseSVN → Revert):丢掉本地未提交的修改,把文件恢复到版本库里的样子。这个操作会真的删掉你的改动,不可恢复,没有回收站。Revert 对话框里可以按文件勾选,改动前建议先用「Check for modifications」看一眼清单。
- Revert changes from this revision(在 Show log 里右键某个版本):这是反向合并,把某个已提交版本的改动反做一遍到你的工作副本,之后还要正常提交才生效,历史里会多出一个新版本。它不是删除历史。
要「撤销一个已经提交的版本、但保留历史记录」,只能走第二种;直接删版本在 SVN 里做不到(这正是它和 Git 思路不同的地方)。
3. Clean up 里藏着一个删除未版本文件的功能
右键 → TortoiseSVN → Clean up,除了常规的修复时间戳、清理锁,对话框里还有 Delete unversioned files and folders 和 Delete ignored files and folders 两个勾选项。
这是清理编译产物最快的方式——比如你想把工作副本里的 bin/、obj/、node_modules/ 一次性删掉但保留版本控制的文件,只要先配好忽略规则,然后勾上「Delete ignored files and folders」跑一次即可。注意这个删除同样不进回收站,勾之前确认忽略规则是准的,否则可能把你没提交的新文件当未版本文件删掉。
其他值得知道的操作
| 操作 | 用法要点 |
|---|---|
| Show log | 默认读本地缓存,别人刚提交的记录可能看不到,点 Refresh 强制回服务器拉;「合并版本」等操作都要在这里右键 |
| Blame | 逐行标出最后修改人和版本,配合「Blame previous revision」可以顺着历史一路往回追 |
| Revision graph | 可视化分支/标签/合并关系,分支多了之后这是理清脉络最有效的工具 |
| Repo-browser | 直接操作服务端,不需要本地工作副本就能建目录、删文件、看版本 |
| Shelve / Unshelve | 1.10 起的暂存功能,把半成品挂起再切去处理别的事,取代了 1.8/1.9 那个实验性的 Checkpoint |
| Changelist | 提交对话框里可以把改动分到不同的 changelist,只提交其中一组 |
四、忽略文件:三层机制,别配错层
这是新手最容易乱的一处,因为 TortoiseSVN 里能配忽略的地方有三个,语义完全不同:
| 机制 | 配置位置 | 作用范围 | 是否提交到版本库 |
|---|---|---|---|
svn:ignore |
右键目录 → TortoiseSVN → Properties | 只作用当前目录,不递归 | 是,团队共享 |
svn:global-ignores |
同上(1.8+) | 递归作用该目录及所有子目录 | 是,团队共享 |
| Global ignore pattern | Settings → General → Global ignore pattern | 本机当前用户的所有工作副本 | 否,纯本地设置 |
选哪层很简单:团队都该忽略的(编译产物、IDE 配置)用 svn:global-ignores 属性,只影响自己的(个人笔记、编辑器临时文件)用设置里的全局忽略。 只在顶层配一次 svn:global-ignores 比在每个目录配 svn:ignore 省事得多——这就是 1.8 引入它的原因。
一个典型 .NET 项目的顶层忽略规则:
bin
obj
.vs
*.user
*.suo
packages
TestResults
坑:忽略规则对已经提交的文件无效
如果 bin/ 早就被提交进仓库了,再加忽略规则什么都不会发生——忽略只影响「未版本控制」的文件,管不了已在版本里的。
正确做法是两步:先把它从版本库删除但保留本地文件(右键 → TortoiseSVN → Delete (keep local),或者命令行 svn delete --keep-local),提交这次删除,然后再加忽略规则。顺序反了就得再来一遍。
五、锁、分支与冲突
需要独占编辑的文件用 svn:needs-lock
SVN 默认是「拷贝-修改-合并」模型,不禁止并发编辑。对二进制文件(图片、Office 文档、设计稿)这种合并不了的类型,应该给文件设 svn:needs-lock 属性:设好之后文件在本地默认是只读的,必须先「Get lock」才能编辑,从而把并发修改挡在源头。
配套的纪律是:编辑完尽快提交并释放锁。锁没释放,别人就是干等,SVN 不会帮你自动解锁。
分支和标签在服务端就是复制
TortoiseSVN 的 Branch/Tag 是在服务端做一次复制操作,瞬间完成、不占额外空间(内部是共享存储),所以别犹豫「建分支会不会很慢」——不会。要遵守的只有一条约定:不要往 tags 目录里提交,标签的语义就是只读快照,提交了就失去意义了。
在分支间切换用 Switch,把分支改动合并回主线用 Merge:
- Merge a range of revisions:最常用的场景,把分支上的若干个版本合并到当前工作副本。想反复同步主线到分支、或者把分支收回到主线,都用它。
- Merge two different trees:需要按「两个点之间的差异」来合并时用,比范围合并更灵活也更难用。
- Reintegrate 选项已经没有了:1.8 起 TortoiseSVN 会自动识别该用哪种合并方式,老教程里让你勾「Reintegrate a branch」的步骤可以直接跳过。
合并完成后是本地修改状态,要检查后再提交。合并信息会写进 svn:mergeinfo 属性,不要手工去编辑它,那是 TortoiseSVN 判断「哪些版本已经合过了」的唯一依据,改坏了会出现重复合并或漏合并。
冲突:先 Update,再解决,最后提交
提交时提示 out of date,说明有人在你这段时间提交过了。标准流程是:
- 先 Update,让服务器上的改动下来。
- 有冲突的文件会标红(红色覆盖图标),文件里出现
<<<<<<</=======/>>>>>>>标记,同时生成.mine、.rXXX这些副本文件。 - 双击冲突文件 → Edit conflicts,用 TortoiseMerge 三方对比逐个区块选「用我的」还是「用他们的」,或者手工改。
- 改完点 Mark as resolved(或 TortoiseSVN → Resolved),把
.mine之类的临时文件删掉。 - 再把整个改动一起提交。
别在没 Update 的情况下反复点提交,也别用「Resolve conflict using mine」把对方的改动整体覆盖掉——那等于把别人的工作悄悄回滚了,是团队协作里最招人恨的一种误操作。
六、工作副本的内部结构(1.7 之后变了,很多人不知道)
Subversion 1.7 是一次大改,工作副本的形态和 1.6 完全不同。如果你是从老教程学来的,下面几条要更新一下认知:
| 项目 | 1.6 及更早 | 1.7 及以后(现在) |
|---|---|---|
.svn 目录 | 每个目录下都有一个 | 只有工作副本根目录有一个 |
| 元数据存储 | 一堆散文件 | 单个 SQLite 数据库 .svn/wc.db |
| 原始文件副本 | 存在 .svn/text-base | 存在 .svn/pristine/,按内容哈希存放 |
由此推出的几条实操结论:
- 可以整体复制工作副本(比如整个文件夹拷到另一块盘),1.7 之后这是受支持的;但不能只拷贝子目录到别处当独立工作副本用,因为它脱离根目录的
.svn就什么都不是。 - 磁盘占用比代码本身大得多。
pristine/里存着每个文件的原始副本,一个大仓库的工作副本占几个 G 是常事。 wc.db是 SQLite,会被锁。 同时开两个工具(比如 TortoiseSVN 和 IDE 里的插件、或者命令行 svn)大幅操作同一个工作副本,可能撞上 SQLite 锁,报 database is locked。这时候关掉其它工具,等一会儿重试即可,不要手工去删wc.db。- 工作副本格式升级不可逆:新版 TortoiseSVN 打开旧格式工作副本会提示升级,升完之后老版本客户端就再也打不开了。如果团队里有人还在用老客户端,升级前先确认。
- 工作副本不要放在网络共享盘上。 锁语义和文件监视在 SMB 上都不可靠,典型症状是图标状态错乱、提交时报各种锁错误。仓库在服务端怎么放是一回事(那是 VisualSVN Server 的事),工作副本必须在本地磁盘。
- 工作副本目录应该加进杀毒软件的排除列表。 实时扫描会频繁打开
pristine/和wc.db,既拖慢状态扫描,也容易撞上文件锁。 - 工作副本坏了,重新 checkout 通常比修更划算。 但记得先把本地未提交的改动导出成 patch(右键 → Create patch)带出来,否则一并丢失。
七、命令行与自动化
装了安装向导里的「Command line client tools」之后,svn 命令就能用了(脚本里最常用的还是它)。但 TortoiseSVN 自己还提供了一组 GUI 命令,可以在批处理里调起它的对话框:
TortoiseProc.exe /command:commit /path:"D:\work\MyProject" /logmsg:"修复登录超时" /closeonend:3
| 参数 | 说明 |
|---|---|
/command: | 要执行的动作,如 commit、update、log、revert、checkout、repostatus |
/path: | 目标路径,多路径用 * 分隔 |
/logmsg: | 预填提交日志 |
/closeonend: | 对话框结束后的行为:0 不关、1 无错误才关、2 有错误也不关、3 一律关闭 |
/notempfile | 配合 repostatus 把结果输出到标准输出,便于脚本解析 |
注意 TortoiseProc 拉起的是图形界面,在无人值守的脚本里不适合当自动化工具用——那种场景应该直接用 svn.exe,或者用 svn status --xml 这类结构化输出配合脚本处理。
八、避坑清单
- 只改文件名大小写会提交失败或无变化。 Windows 文件系统不区分大小写、SVN 区分,
readme.txt改成Readme.txt需要两步:先改成Readme2.txt提交,再改成Readme.txt提交。 - 删除文件要用 TortoiseSVN → Delete,别用 Windows 的删除。 直接用资源管理器删掉再提交,SVN 能识别成删除,但如果你删完又提交了别的、或者中途 Revert,状态容易乱。右键 Delete 是明确的「我要从版本库删掉它」。
- 提交前一定看 diff。 提交对话框里双击文件名就能看差异,这一步能拦掉绝大多数误提交(尤其是把调试代码和临时文件带上去)。
- 别提交编译产物和大二进制文件。 SVN 的服务端存储对这类文件很不友好——一旦提交,即使后续删掉,历史里的体积也永久存在。用
svn:global-ignores提前拦住。 - Show log 看到的是缓存。 排查「别人明明提交了为什么我这看不到」时,点 Refresh 拉服务器的最新记录。
- 不要手工编辑
svn:mergeinfo、不要删wc.db、不要改.svn里的东西。 这三样坏掉之后能救回来的概率很低。 - 勾选 Clean up 里的删除选项前先确认忽略规则。 「Delete unversioned files」不区分「垃圾」和「你刚写好还没提交的新代码」,两者都是未版本文件。
- 锁用完记得释放。 设了
svn:needs-lock的文件,锁不放别人就只能干等,SVN 不会自动超时释放。
小结
| 环节 | 关键点 |
|---|---|
| 安装 | 1.14.9 / 需 Win10+;记得勾 Command line client tools;装完重启资源管理器 |
| 图标不显示 | Windows 只有约 11 个覆盖槽位,先试 Settings → Overlay Handlers 重排,再考虑改注册表 |
| 易错命令 | Update to revision 是粘性的;Revert 不可恢复;反向合并要再提交一次 |
| 忽略规则 | 团队共享用 svn:global-ignores,本地用 Global ignore pattern;对已提交文件无效 |
| 分支合并 | 分支是服务端秒级复制;Merge 后要提交;不要碰 svn:mergeinfo |
| 工作副本 | 只根目录一个 .svn + wc.db;不放网络盘;加杀毒排除;坏了重拉比修快 |
一句话总结:TortoiseSVN 本身的命令没几个,真正需要花心思的是它和 Windows 交界的那几处——图标覆盖的排位赛、安装向导里的默认选项、工作副本的本地磁盘要求。把这三处理顺,剩下的日常操作基本不会出岔子。
评论区