如何在Subversion中回退到旧版本的代码?

524

我正在和朋友一起开展一个项目,想要回到我们代码的早期版本,并将其设置为当前版本。我该怎么做?

我正在使用vs08上的"anksvn"。

我在我的电脑上拥有我想要的版本,但提交失败了。我得到的消息是“提交失败,文件或目录已经过期。”

我也在我的电脑上安装了subversion客户端。

14个回答

840

基本上你需要“向后合并”-将当前版本和上一个版本之间的差异(diff) 应用于当前版本(这样你就可以得到一个看起来像旧版本的工作副本),然后再次提交(commit)。所以例如,要从版本150(当前版本)返回到版本140:

svn update
svn merge -r 150:140 .
svn commit -m "Rolled back to r140"

Subversion红皮书中有一个很好的章节介绍了这个。


79
如果您正在使用TortoiseSVN,右键单击文件,选择合并,然后选择“合并一系列版本”。在日志框中输入140-150,并勾选“反转”复选框。之后,像往常一样提交。这将执行与Jon示例相同的操作。 - DavGarcia
11
使用Eclipse和Subclipse,您可以右键单击项目,选择Team/Show History,然后选择要“撤消”的修订版本,并通过另一个右键单击选择“从所选修订版本中还原更改”。 - fego
37
要从主干版本回滚,您还可以编写svn merge -r HEAD:140 - sschmeck
4
@DavGarcia的TortoiseSVN说明对我来说不太准确,至少不能用来还原一个版本中的所有文件(使用TortoiseSVN 1.8.8)。右键单击文件夹,选择TortoiseSVN->显示日志。选择您想要还原的版本,右键单击并选择“恢复此版本的更改”。提交更改。 - mhenry1384
4
请注意合并命令末尾的句点(.)。 - AbD_Riz
显示剩余12条评论

184

你只能在subversion历史记录的头部提交新更改。

不能直接使用计算机上的优秀副本,因为它的.svn文件夹知道它是过去的代码,所以在提交之前需要更新。

找到好的修订版本号并还原

  1. 找到您想要的旧副本的修订版本号。

    使用以下命令获取您当前的修订版本号:

    svn info --show-item revision
    # or
    svn log
    

    或者要检查您项目的版本,请使用:

    svn update -r <earlier_revision_number>
    

    直到找到正确的修订版本号。

  2. 记录下好的修订版本号(以下示例假设为123)。

  3. 更新至最新修订版本:

  4. svn update
    
  5. 撤销从你想要的版本到最新版本之间的所有更改:

  6. svn merge -r HEAD:123 .
    svn commit -m "Reverted to revision 123"
    

    (与Jon Skeet上面的答案相同)

如果您找不到修订版本号

如果您找不到旧版本,而您只想提交当前电脑上的文件:

  1. 复制您的好版本(但不带任何.svn文件夹):

cd ..
rsync -ai --exclude=.svn  project/  project-good/
  • 现在确保你拥有最新版本:

  • cd project
    svn update
    # or make a fresh checkout
    svn checkout <url>
    
  • 复制你的好版本覆盖工作副本。

    这个命令会复制,并删除工作树中不在你的好版本里的任何文件,但它不会影响现有的 .svn 文件夹。

  • cd ..
    rsync -ai --exclude=.svn --delete  project-good/  project/
    

    如果你没有rsync,你可以使用cp -a,但你还需要手动删除任何不想要的文件。

  • 你现在应该能够提交你所拥有的内容。

  • cd project
    svn commit -m "Reverted to good copy"
    

    2
    svn不会将其解释为修改,我无法提交。 - Sandburg
    我猜这个答案被那些找不到他们的修订号码或欣赏领先解释的人点赞了。我现在已经更新了答案,包括两种方法。 - joeytwiddle
    1
    svn commit -m "回滚到好的版本",你漏掉了 -m。 - Salim Shamim
    1
    @SalimShamim 谢谢,它已经失踪了12年。 - joeytwiddle
    在第一个案例的第4步(我有修订号码的地方),当运行svn merge -r HEAD:revnumber时,会出现“需要合并源”的提示。 - Kevin Crum

    35

    只需使用此行命令:

    svn update -r 你的旧版本号

    你可以通过以下命令知道当前的版本号:

    svn info


    16
    这并没有解决问题,反而表现了提问者在提问时的状态。 - Ingo Schalk-Schupp
    3
    如果你不幸地按照这个建议去做了,运行以下命令:“svn resolve --accept working -R .”。请注意,这是一个命令行操作。 - Owl

    28

    如果您想撤销整个检入,使用合并的标准方法非常有效。但有时候,您只想还原单个文件。没有正当的方法可以实现,但有一种技巧:

    1. 使用svn日志查找您想要的版本。
    2. 使用svn导出子命令:

      svn export http://url-to-your-file@123 /tmp/filename

    (其中123是文件好版本的修订号。)然后将该单个文件移动或复制以覆盖旧文件。检入修改后的文件,完成操作。


    使用Tortoise-svn,我可以右键单击一个文件并合并它。使用svn也应该有一种方法来实现这个功能吧? - lc.
    10
    将工作副本中路径为"path-in-your-working-copy",版本号为123的文件内容输出到该路径下的同名文件。 - dash17291

    9

    有点老派

    svn diff -r 150:140 > ../r140.patch
    patch -p0 < ../r140.patch
    

    然后按照通常的做法进行。
    svn diff
    svn commit
    

    5

    我认为这是最合适的方法:

    反向合并,例如,如果提交的代码包含从rev 5612到5616的修订版本,只需向后合并即可。在我的环境中可以正常工作。

    例如:

    svn merge -r 5616:5612 https://<your_svn_repository>/
    

    这将包含一个合并的代码返回到先前的版本,然后您可以提交它。


    4
    这是我的做法,对我很有效。
    我想撤销我在多个提交中做的更改,转到以前的提交点。
    1. 转到Team -> Show History。
    2. 右键单击要忽略的修订或修订范围。
    3. 选择“还原更改”选项。
    这将运行一个反向合并,撤消工作副本中的更改。
    只需查看代码并提交即可。

    3

    这个页面上有很多危险的回答。需要注意的是,自从SVN版本1.6以来,执行update -r命令可能会导致树冲突(tree conflicts),并迅速升级为潜在的数据丢失问题,就像卡夫卡式噩梦一样,你需要在Google上搜索有关树冲突的信息。

    恢复到某个版本的正确方法是:

    Original Answer翻译成"最初的回答"
    svn merge -r HEAD:12345 .
    

    在这里,12345是版本号,请不要忘记点号。最初的回答。

    2

    右键单击您想要还原的最高层次结构 >> 还原还原到版本


    2
    大多数之前的答案都使用了反向合并,这通常是正确的答案。 但是,在某些情况下(就像刚刚发生在我身上的情况),这不是最佳方案。
    当进行小改动时,我不小心将具有Unix换行符的文件更改为DOS换行符,并提交了它。这很容易被撤消,可以通过更改换行符并再次提交或反向合并来实现,但它会导致svn blame 列出我的编辑作为该文件每一行的来源。(有趣的是,在Windows上的TortoiseSVN没有受到此影响,只有命令行svn blame
    如果您想保留svn blame报告的历史记录,您需要执行以下操作:
    1. 删除文件并提交。 2. 在存储库中,将先前的良好副本复制到头部,并提交。 3. 恢复要保留的任何编辑内容。
    删除可能有点可怕,但请记住,您始终可以在存储库中保存文件,因此恢复它并不是什么大问题。以下是一些代码以说明这些步骤。假设xxx是最后一个良好副本的修订号。
    svn rm svn+ssh://path/to/file
    svn copy svn+ssh://path/to/file@xxx svn+ssh://path/to -m"Restore good copy"
    svn update
    <restore the edits>
    svn commit -m"Restore edits"
    

    请注意,在仓库中复制时,目标需要是一个目录,而不是一个文件名。

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