svn move是唯一能保留完整历史(log/blame/merge)的方式,分工作副本内移动(如svn move trunk/src trunk/app/src)和服务器端移动(如svn move -m "reason" source_url dest_url),跨仓库需用dump/filter/load流程。

必须用 svn move 命令操作,不能用操作系统直接重命名或剪切粘贴。这是唯一能保留完整历史(log/blame/merge 能力)的方式。
工作副本内移动(推荐日常使用)
适用于同一仓库下调整目录结构,比如把 trunk/src 移到 trunk/app/src:
- 确保工作副本已更新到最新版本,且没有未提交的修改
- 在终端执行:
svn move trunk/src trunk/app/src - 运行
svn status确认显示为A +(新增带历史)和D(删除原路径),不是两个独立操作 - 提交时写明重命名意图,例如:
svn commit -m "move src to app/src preserving history"
服务器端直接移动(适合批量或远程操作)
跳过本地工作副本,由服务端原子完成,适合 CI/CD 或管理员操作:
- 命令格式:
svn move -m "reason" SOURCE_URL DEST_URL - 例如:
svn move -m "restructure: move legacy module" https://svn.example.com/repo/trunk/oldmod https://svn.example.com/repo/trunk/modules/oldmod - 该操作立即生效,无需本地检出,所有客户端下次更新即可看到新路径
- 注意:源 URL 必须存在,目标 URL 不能已存在,且必须在同一仓库内
跨仓库迁移并保留历史(非 move,但满足“保持记录”需求)
当目标位置属于另一个 SVN 仓库时,svn move 不可用,需用 dump/filter/load 流程:
- 在服务端导出源库指定路径:
svnadmin dump /path/to/oldrepo > full.dump - 过滤并重写路径:
svndumpfilter include oldpath --renumber-revs --drop-empty-revs filtered.dump - 导入到新库指定前缀:
svnadmin load /path/to/newrepo --parent-dir newroot - 完成后验证:
svnlook tree /path/to/newrepo和svn log -l 5 NEW_URL
常见错误与规避方法
这些操作看似相似,实则会切断历史:
- 在资源管理器或 Finder 中直接重命名文件夹 → SVN 视为删除+新增,
svn log查不到旧路径记录 - 先
svn delete再svn add同名新路径 → 历史链断裂,分支合并可能失败 - 用
cp+svn add复制后删原目录 → 新文件无任何先前提交信息 - 跨仓库拖拽(如 TortoiseSVN 右键拖动到另一仓库地址)→ 操作被拒绝或静默失败,不报错但不生效











