将整个svn代码库回滚或还原到早期版本

76

我在SVN仓库上搞砸了,现在需要将整个仓库从版本28还原到24,但不想处理差异或冲突。是否有快速简便的方法来完成这个操作?我以前能够使用合并命令成功地回退单个文件,但在这种情况下,它想要将所有文件从版本28添加回仓库,而我真正想做的只是删除它们。

我在Linux系统(bash)上使用命令行。

谢谢

编辑

感谢大家的帮助!我通过以下方式解决了问题:

svnadmin create /svnroot/<repo>.fixed
svnadmin dump -r 1:24 /svnroot/<repo> --incremental > dump.svn
svnadmin load /svnroot/<repo>.fixed < dump.svn

然后将旧的存储库放在备份位置,将repo.fixed移动到repo。

再次感谢!


3
谢谢你。我正在学习svn并搞糟了一些目录的移动(结果发现我曾有个理由把它们放在那儿!),我想要把这些改变撤销。你的问题帮我省了很多麻烦。 - AgentConundrum
谢谢,我相信这个可行,但当你的仓库有10,000多个版本时,需要很长时间。:( - Amir Pashazadeh
14个回答

26

请查看svnadmin dump/load。它会创建一个包含您文件每个版本的文本文件。可能可以删除特定点上下的所有内容,然后重新导入。

例如,请参见将存储库数据迁移到其他地方


2
我现在正在研究这个问题,谢谢。当然,我本来就会无意中输入 "svnadmin dump" 而没有进行管道操作,所以现在我的整个项目正在被写入标准输入流并且不能通过按下 ctrl+c 终止... 我不会再犯同样的错误了 :p - user19302
好的,我现在走上了正确的轨道,谢谢!但是我该如何使它保留我的修订记录呢?我编写了一个 Perl 脚本,用于 1 到 24 的 "svnadmin dump -r $i:$i+1 <repos> > file",然后 "svnadmin load <repos> < file",但它只提交了修订版本 1。 - user19302
1
在更改历史记录时重新加载备份时,请确保更改存储库的GUID。否则,您可能会使用具有更改数据库的旧工作副本,并在稍后获得神秘破碎的修订版本(因为它们是基于不再存在的版本构建的增量)。 - Bert Huijben

25

您可能需要进行“反向”合并。请参阅svn书籍中的“撤消更改”部分。

例如, svn merge -r 28:24 [svn路径]


它不会删除在28创建的文件。问题在于我添加了一堆不该添加的文件。是的,我真的搞砸了。手动追踪需要删除的内容是不可能的。我只想删除24之后的每个版本。 - user19302
2
抱歉 - 我可能没有完全理解您的问题。我曾多次使用反向合并来消除新添加的(但不正确的)文件...(但您的情况可能略有不同?) (通常情况下,您无法从svn存储库中删除修订版本 - 只能添加新版本以修复错误)。 - luapyad
你所需做的就是合并回去,如答案所示,然后将项目检入 (svn ci -m "将所有更改还原到修订版本 X")。仍然可能可以检出错误的修订版本,但这将把你想还原的修订版本放在 HEAD。 - Niko

14
如果您可以访问SVN服务器,您只需编辑path/db/current,在其中输入要还原到的旧版本号(此处为24),并从path/db/revs/0/中删除不再需要的修订文件(即25、26、27、28)。至少在我今天意外删除存储库中的一个目录后,这种方法是有效的。

到目前为止,最快、最简单的方法是使用这个技巧。虽然我以前用过这个技巧,但这是一个不好的习惯。在任何其他人正在使用或包含关键数据的存储库中,我都不会这样做。最好通过管理工具正确地进行操作。 - Tynam
我不知道所有可能发生的事情,但我知道这样做可能会在以后造成麻烦,因为我曾经在这样做之后的下一次提交中遇到过问题。话虽如此,我已经成功地做了几次,当然你备份了你的仓库,对吧?(当然,一个明显的问题是旧的工作副本缓存的仓库状态与实际仓库不匹配,所以一定要立即进行全新的检出并从那里开始工作,否则不匹配很可能会导致提交问题。) - Tynam
哦,这很脏……但似乎可以工作。然而,我必须运行 svnadmin recover /path/to/repo 才能再次提交。 - lxg
值得注意的是,如果您的提交次数少于1000次,则文件仅位于path/db/revs/0。如果您的提交次数超过1000次,则文件位于path/db/revs/X,其中X是提交编号除以1000的结果。 - Michael Firth

13

如果你确实需要清除文件曾经存在的"痕迹",你需要执行上述所描述的svndump/svnload操作。

在“正常”的情况下,如果你犯了错误,你需要使用逆向合并(reverse merge)。这可以确保撤销r24之后的更改也可以被还原、差异化等。

以下命令应该可以撤销你的更改(你需要提交合并结果以反映仓库中的合并)

svn merge -r 28:24

1
哈哈,我可以详细解释这不是一个“正常”的情况,但我宁愿不再让自己难堪。 - user19302
1
“异常”情况指的是,如果您提交了一些秘密内容,例如包含密码等文件,那么您需要将其完全删除。最新消息是关于“svn obliterate”的启动正在进行中。 - Sander Rijken

6
如果您没有管理员权限,则无法消除任何旧版本,但是您仍然可以使用一个非常简单的“svn copy”命令将它们隐藏得非常好(nickf和JesperE已经提到了这一点,但方式有些神秘)。

svn delete protocol://svnserver/some/resource
svn copy protocol://svnserver/some/resource@24 protocol://svnserver/some/resource

那就是了,版本25到28已从svn日志中完全消失。 这不是黑客行为,而是一项安全且(几乎...)记录在案的功能。
如果“resource”是一个目录,则必须从最后一个URL中剥离它:

svn copy protocol://svnserver/some/directory@24 protocol://svnserver/some/

(否则,您会将其复制到自身内部)。

如果svn copy prot://srv/path/proj ...命令出现错误,例如"svn: E170000: ... isn't in the same repository as ...",那么你可以通过执行svn checkout prot://srv/path/proj@321 coolver然后svn copy coolver/proj prot://srv/path/来解决它;# ftw! - MarkHu

4

如果您正在使用TortoiseSVN,则解决方案很简单:

  • 查看变更日志
  • 右键单击要回滚到的版本...
  • ...选择“还原到此版本”
  • 提交您的更改

这种方法可以保留版本历史记录(即您还原的所有修订版本)。


我基本上使用了你在这里提到的方法,因为版本历史得以保留,但我的做法是删除了我的工作副本的源代码,然后选择了“更新项目到修订版”(因为“还原到此修订版”并没有退出在该修订版之后创建的文件)。对于TortoiseSVN用户来说,这是一个很好的解决方案 :) - Ignacio Rubio
我非常确定这个问题是关于删除历史记录的。 - MarcH
这个选项在TortoiseSVN中不存在,至少在2018年不是。 - Rockin4Life33

3

我已经做过了,但它拒绝将其作为新版本提交回存储库。这是可能的吗?即将版本29变成版本24的副本? - user19302
是的。svn复制命令可以进行仓库到仓库的复制。请查看“svn help copy”以获取确切的语法。 - JesperE

2
如果您的应用程序文件夹结构没有改变,请检出旧版本,并将最新版本的 .svn 文件夹替换到已检出的旧版本中。现在您可以提交“旧”的版本。

2
说实话,这听起来像是一个黑客攻击。 - Sander Rijken
很不幸,文件夹结构发生了重大变化,否则我就可以手动删除需要删除的内容了。还是谢谢你的建议。 - user19302
1
我同意这是一个hack;但这只是一个特殊情况,所以我不确定是否要寻找最优雅的解决方案。一些快速简单的东西就足够了。 - neesh

1

如果您真的想完全从存储库中删除文件,则需要将其作为 svndump 导出到文件中,过滤掉不需要的版本和/或文件路径,创建一个新存储库,然后将已过滤的导出内容 svnload 到新存储库中。在执行任何此类操作之前,您需要仔细阅读《SVN 书籍》中关于存储库维护的章节,并确保在确定新存储库具有所需内容之前不要删除现有存储库。


1

你可以先使用svn del命令删除最顶层的目录,然后再使用svn copy命令重新复制它们:

svn copy svnurl@version svnurl 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接