【问题标题】:Retract accidental checkin撤回意外签到
【发布时间】:2010-10-19 08:42:24
【问题描述】:

您正在使用 subversion 并且您不小心在一些代码准备好之前签入了它。例如,我经常:a) 签入一些代码,然后 b) 稍微编辑,然后 c) 敲击,回车重复上一个命令,不幸的是这是签入。

是否可以通过 subversion 从服务器中撤回这种意外签入?

【问题讨论】:

标签: svn


【解决方案1】:

是的,这确实是 Subversion 的用途。

您需要做的只是将您的副本替换为 SVN 存储库中的先前版本。

有几种选择:

  1. 替换为修订版。
  2. 替换为网址
  3. 存储库中的最新版本(但在您的情况下,您已经拥有最新版本)
  4. 用分支替换

但我强烈建议您在替换本地副本之前执行以下操作:

  1. 执行“与存储库/修订/URL 比较”。

【讨论】:

  • 那只会改变本地副本。我想从服务器撤回签到。
  • 如果您真的不想留下任何历史记录,您可以随时删除整个存储库并重新创建它。
【解决方案2】:

我会怀疑。源代码控制的主要思想之一是存储库不会丢失任何历史记录。您无法删除历史记录。您能做的最好的事情是获取旧版本并用它覆盖当前版本。但是历史日志仍然会显示你的错误。

(题外话:你正在使用什么样的 IDE 来做这样的事情?)

【讨论】:

  • 呵呵,使用 vim + 单独的 shell 进行签入
  • 建议:使用集成了 SVN 支持的 IDE。容易多了。 :)
  • 能力越大,责任越大。 另一个快乐的 VIM 和独立的 shell 用户在这里。对于 VIM 和 Bash 提供的强大功能和速度,我很乐意偶尔遇到这样的“意外”。
  • 这个时代我是 TortoiseGit 的坚定支持者。 :) 尽管 Visual Studio 确实具有基本的 Git 支持,但它仍然与 Tortoise 的功能相去甚远。而且,是的,我知道 - 命令行更加强大(我仍然更喜欢 Tortoise 来完成 99% 的日常工作)。 :)
【解决方案3】:

使用 TortoiseSVN,选择 Show log 并找到要恢复到的版本。从上下文菜单中,选择恢复到此版本。这会对您的工作副本执行反向合并,因此您必须提交您的工作副本才能完成操作。

另见How do we keep track of our working copy's branch? :-)

【讨论】:

    【解决方案4】:

    请参阅SVNBook,特别是“撤消更改”部分,然后进行反向合并。

    svn merge 的另一个常见用途是回滚已经提交的更改。假设您在 /calc/trunk 的工作副本上愉快地工作,并且您发现在修订版 303 中所做的更改(更改了 integer.c)是完全错误的。它不应该被提交。您可以使用 svn merge 来“撤消”工作副本中的更改,然后将本地修改提交到存储库。您需要做的就是指定一个反向差异:

    $ svn merge -r 303:302 http://svn.example.com/repos/calc/trunk

    为了澄清,您的初始更改将仍然在存储库中。但是您现在在以后的修订中收回了它。即存储库已捕获您的所有更改(这确实是您想要的!除非您签入明文密码或类似密码!)

    【讨论】:

    • 这是一个可行的解决方案。谢谢。
    • 做同样的事情,但我更喜欢 svn merege -c -303 来撤销更改。似乎更容易让人理解。
    • @JeremyFrench -c 在 -r 不太清楚为什么的地方工作,但感谢 1M!
    • 呸!谢谢节省了一些头发拉
    【解决方案5】:

    您无法撤回修订,您最多只能恢复到先前的修订并再次签入。

    【讨论】:

      【解决方案6】:

      您无法删除修订 - 这里的几个答案似乎完全误解了您想要的内容。但是您可以更改签入消息以表明它是无意的。签到的费用并不高,所以多加一个也没什么大不了的。

      【讨论】:

      • 这是错误的,根本没有解决问题。上面的 Brian Agnew 和 David Fraser 有更好的想法。
      【解决方案7】:

      也对此发表评论:这是我在存储库上执行的一系列命令,用于将其从修订版 2 恢复到修订版 1。不过,您也需要在最后签入。

      Last login: Mon Apr 13 16:01:34 on ttys004
      [wlynch@orange ~] cd /tmp
      [wlynch@orange /tmp] svnadmin create foo
      [wlynch@orange /tmp] svn co file:///tmp/foo foo-repo
      Checked out revision 0.
      [wlynch@orange /tmp] cd foo-repo/
      [wlynch@orange foo-repo] ls
      [wlynch@orange foo-repo] touch blah
      [wlynch@orange foo-repo] touch repl
      [wlynch@orange foo-repo] touch bar
      [wlynch@orange foo-repo] svn add *
      A         bar
      A         blah
      A         repl
      [wlynch@orange foo-repo] svn ci
      Adding         bar
      Adding         blah
      Adding         repl
      Transmitting file data ...
      Committed revision 1.
      [wlynch@orange foo-repo] echo "hi" > bar
      [wlynch@orange foo-repo] echo "oh no" > blah
      [wlynch@orange foo-repo] svn ci
      Sending        bar
      Sending        blah
      Transmitting file data ..
      Committed revision 2.
      [wlynch@orange older-foo] svn diff -r 1:2 file:///tmp/foo
      Index: bar
      ===================================================================
      --- bar (revision 1)
      +++ bar (revision 2)
      @@ -0,0 +1 @@
      +hi
      Index: blah
      ===================================================================
      --- blah    (revision 1)
      +++ blah    (revision 2)
      @@ -0,0 +1 @@
      +oh no
      
      [wlynch@orange foo-repo] svn diff -r 1:2 file:///tmp/foo | patch -R
      patching file bar
      patching file blah    
      

      【讨论】:

        【解决方案8】:

        如果您的意思是,我如何干净地删除意外签入的历史记录: 这很难。

        svn 不允许您撤消任何操作,因为它将修订保存为变更集。 但是,有一些工具可以让您对存储库的转储执行几乎任何操作。 你可以

        1. 转储您的存储库。

        2. 使用svn admin tools 中的svndumpfilter 来取消签入。

        3. 将其放回 repo。

        但这可能会彻底毁掉你的 repo,所以永远不要尝试这样做,除非你完全知道自己在做什么并且已经备份了所有内容。

        【讨论】:

        • 我正要发布这个... +1 击败我
        • 哦,你要找的工具是“svndumpfilter”,IIRC
        【解决方案9】:

        注意:这可能不适用于当前版本的 SUBVERSION 并且是一个坏主意 - 但我将其留在这里以供参考

        注意: 通常,当您错误地签入时,您应该只恢复提交 - 请参阅此问题的其他答案。但是,如果您想知道如何实际撤消提交的影响并将存储库更改为以前的样子,下面有一些解释:

        这不是您通常想要的,但如果您真的想要从存储库中删除实际提交的版本,那么您可以按如下方式对存储库进行令人讨厌的回滚(假设$REV 设置为您要删除的最新版本):

        • 首先备份您的存储库,因为这些更改可能会破坏它(并阅读以下假设)
        • 将您的本地副本恢复到以前的版本,以免混淆 (svn revert -r $((REV-1)))
        • 在存储库中,删除 db/revs/$REVdb/revprops/$REV
        • 在存储库中,删除 db/current 和(对于 subversion 1.6 或更高版本)db/rep-cache.db,然后运行 ​​svnadmin recover .
        • (可能)调整db/rep-cache.db 的权限以防止尝试写入只读数据库 错误

        这一切都假设:

        • 您正在使用基于 fsfs 的存储库
        • Subversion 版本大于1.5.0(否则您必须手动编辑db/current 并更改修订号而不是运行svnadmin recover .
        • 未提交任何其他后续修订
        • 您对存储库的文件系统具有写入权限
        • 执行上述操作时,您不必害怕其他人试图访问它

        当一个巨大的文件被提交到一个我不想永远留在历史(和镜像等)中的存储库时,我已经做到了;这绝不是理想或正常的做法......

        【讨论】:

        • 这真是错误的做法!下面的答案是正确的方法。
        • 因此上面有nasty这个词!我给出了答案,因为提问者询问了关于实际撤回签到的问题;当然,提交合并的回滚通常是您想要做的。使用更智能的版本控制系统也使这些选择更容易:)
        • 说真的,除非提交会给 repo 造成重大负担,或者刚刚发生的更改,否则损坏 repo 的风险是巨大的。
        • 这只是发生在我身上,不得不通过 chmod 重新调整它的权限。除此之外,它效果很好,而且你的文字非常清晰,所以不需要编辑。
        • -1 用于使用此方法的 repo 损坏。我同意有时需要以丢失数据的方式更改存储库,并且 svn revert 不会这样做。然而,这个过程......我们只是尝试过它并且它破坏了repo(svnadmin:E200002:序列化散列缺少终止符)。我们发现,由于我们只是删除了最新的修订版,svnadmin 转储到倒数第二个修订版,然后将 svnadmin 加载到新的 repo 中完全符合我们的要求,并且完全没有破坏性。
        【解决方案10】:

        警告:接受的答案(David Fraser)应该适用于 SVN 1.5 存储库,但对于 SVN 1.6,您还必须在下一次提交之前删除 db/rep-cache.db,否则 您将损坏您的存储库,并且可能直到您下次尝试完整结帐时才意识到这一点。我看到后续的完整结帐失败并出现“格式错误的表示标头”错误。

        您可能会问,什么是 rep-cache.db? documentation on the FSFS layout 表示如果您删除此文件,您将失去“代表共享功能”;但是,它将在您的下一次提交时重新创建。 Representation sharing was added in 1.6.

        【讨论】:

        • 对不起,你的答案在哪里??
        • 我现在更喜欢在每次提交之前备份存储库。这样,如果我意识到我犯了一个错误,我可以简单地删除整个存储库并从备份中快速恢复它@以前的修订版,而不必担心存储库内部。一盎司的预防……
        • 谢谢,我已经编辑了我的答案以合并上述内容以降低损坏风险
        【解决方案11】:

        有时需要在服务器上编辑存储库,例如当您不小心提交了一个难以更改的密码时。这是我认为完全安全的方法(@David Fraser 的回答对我造成了回购损坏)。请注意,此方法只会从 repo 末尾删除修订,因此如果您立即发现错误,则最有用。

        1. 通知您的所有用户该存储库正在离线,他们需要从服务器创建一个新的结帐。
        2. 使存储库脱机,制作备份副本并将主存储库移动到名称类似于 reponame_old 的安全位置。
        3. 将您的 repo 转储为单个文件表示,将不需要的修订留在最后:
          • svnadmin dump -r 0:N > reponame.dump
          • 例如svnadmin dump -r 0:6610 > reponame.dump 将删除 6611 以后的版本
          • 请注意,repodump 文件可能是您的 repo 文件夹大小的两倍。
        4. 创建一个新的存储库以将这些修订加载到:
          • svnadmin create reponame
        5. 将修整后的修订集加载到新的存储库中
          • svnadmin load reponame < reponame.dump
        6. 对您的新存储库应用任何必要的自定义(例如钩子)并将其恢复使用。
          • 我们正在使用 VisualSVN 服务器,因此必须恢复 conf\VisualSVN-WinAuthz.ini 文件。
          • 在我们重新启动服务器之前,我们还看到了一些奇怪的行为,因此 VisualSVN 可能会缓存 repo 状态; YMMV 与其他托管设置。
        7. 不要忘记删除包含机密数据的备份,或者将其放在安全的地方。
        8. 告诉所有用户从 repo 服务器创建一个新的svn checkout

        【讨论】:

        • PS 你应该定期备份你的 repo。
        • PPS 你应该使用 git ;)
        猜你喜欢
        • 2014-03-07
        • 2018-04-26
        • 2014-05-19
        • 1970-01-01
        • 1970-01-01
        • 2015-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多