【问题标题】:examining history of deleted file检查已删除文件的历史记录
【发布时间】:2010-09-28 21:59:56
【问题描述】:

如果我在 Subversion 中删除一个文件,我如何查看它的历史和内容?如果我尝试对不存在的文件执行svn catsvn log,它会抱怨该文件不存在。

另外,如果我想恢复文件,我应该只用svn add 恢复它吗?

(我专门询问了 Subversion,但我也想了解 Bazaar、Mercurial 和 Git 是如何处理这种情况的。)

【问题讨论】:

    标签: svn version-control bazaar


    【解决方案1】:

    当你想查看旧文件时,你真的应该知道它们之间的区别:

    svn cat http://server/svn/project/file -r 1234
    

    svn cat http://server/svn/project/file@1234
    

    第一个版本查看现在作为http://server/svn/project/file 可用的路径,并检索该文件,因为它在修订版 1234 中。(所以这个语法工作文件删除后)。

    第二种语法获取在修订版 1234 中作为 http://server/svn/project/file 可用的文件。因此,这种语法DOES适用于已删除的文件。

    您甚至可以结合使用这些方法来检索在修订版 2345 中作为 http://server/svn/project/file 可用但内容与在 1234 中相同的文件:

    svn cat http://server/svn/project/file@2345 -r 1234
    

    【讨论】:

    • 啊,谢谢!目前这个帖子的热门回复没有提到这个,太好了!
    • 这对我来说仍然失败,除非我使用绝对路径,因为当 ./local 目录不存在时,我的本地 svn 客户端在无法解析 ./local/file 时给出错误。对于较新版本的 SVN,这可能不是问题。
    • @DerrickRice:在这种情况下,^ 符号很方便:它指的是存储库根目录,因此您可以说svn cat ^/local/file@REV(取决于存储库根目录和 URL 之间的距离)。
    • 这在原则上很好用。对于文件夹,我收到以下信息:svn: E200009: Could not cat all targets because some targets are directories
    • 这是最好的答案。得票最高。
    【解决方案2】:

    首先,找到文件被删除的修订号:

    svn log -v > log.txt
    

    然后在 log.txt(不是 SVN 大师,所以我不知道更好的方法)中查找带有

    的行
    D <deleted file>
    

    然后查看是哪个版本。然后,与其他答案一样,使用以前的版本恢复文件。

    【讨论】:

    • svn log -v | grep D "文件名"
    • +1 是第一个正确回答问题的人。如果不知道删除前的修订,则无法查看内容。
    • @abatishchev 这会获取已删除文件的列表,但会丢弃修订信息,因此它没有用。如果您正在使用具有大量更改历史的大型/旧存储库,它也会很慢。
    • 很好,@abatishchev 的改进很棒。 tchen:使用 grep 的 -B50 左右参数轻松修复,请参阅我的答案。
    • 另一个限制非常大/旧存储库的 svn log -v 输出的好方法是 -l 选项。所以你可以使用 svn log -v -l 100 | grep D "文件名"
    【解决方案3】:

    要获取已删除文件的日志,请使用

    svn log -r lastrevisionthefileexisted
    

    如果要恢复文件并保留其版本历史记录,请使用

    svn copy url/of/file@lastrevisionthefileexisted -r lastrevisionthefileexisted path/to/workingcopy/file
    

    如果您只想要文件内容但未版本化(例如,为了快速检查),请使用

    svn cat url/of/file@lastrevisionthefileexisted -r latrevisionthefileexisted > file
    

    在任何情况下,都不要使用 'svn up' 来取回已删除的文件!

    【讨论】:

    • 您还可以通过反向合并删除文件的修订版来恢复文件。这是 SVN 文档中推荐的过程。至于使用“svn up”,与其说是“不要做”,不如说是“它不会做你想做的事”。
    • 我怎样才能看到文件的整个历史记录呢?
    • 简单:使用“-v”开关显示父文件夹的日志:您将获得每个条目的更改路径列表。找到前面带有“D”和已删除文件名称的文件。那是文件被删除的版本。
    • 这似乎不适用于已删除的文件。如果我尝试这个,我会收到以下错误消息: svn cat [url]/trunk/include/syeka/poster_funk.incl.php -r 50 > out.txt svn: '/admintools/!svn/bc/131/trunk/ include/syeka/poster_funk.incl.php' path not found 请参阅@Bert Huijben 在此线程下方的响应以获取有效的解决方案。
    • 如果我有一个有 100,000 次提交的仓库,“lastrevisionthefileexisted”不容易找到!
    【解决方案4】:

    在 git 中并没有什么特别之处。如果您知道文件的名称,您可以通过日志找出删除它的更改:

    git log -n 1 -- filename
    

    然后您可以使用该提交来获取删除之前存在的文件。

    git checkout [last_revision]^ filename
    

    示例:

    dhcp-120:/tmp/slosh 587% ls -l slosh.tac
    ls: slosh.tac: No such file or directory
    dhcp-120:/tmp/slosh 588% git log -n 1 -- slosh.tac
    commit 8d4a1f1a94e4aa37c1cb9d329a140d08eec1b587
    Author: Dustin Sallings <dustin@spy.net>
    Date:   Mon Dec 15 11:25:00 2008 -0800
    
        Get rid of a .conf and replace it with .tac.
    dhcp-120:/tmp/slosh 589% git checkout 8d4a1f^ slosh.tac
    dhcp-120:/tmp/slosh 590% ll slosh.tac
    -rw-------  1 dustin  wheel  822 Dec 30 12:52 slosh.tac
    

    请注意,这实际上并没有将文件重新置于修订控制中。它只是将文件以最终状态存在的状态拖放到当前位置。然后,您可以添加它或只是检查它或从那时起进行任何操作。

    【讨论】:

    • 精彩的答案。唯一的问题是问题是关于 svn!
    • 由于帖子没有尝试回答明确有关 Subversion 的原始问题,考虑否决它,以便有机会将其删除。
    【解决方案5】:

    仅使用 GUI 的解决方案:

    如果您知道文件的名称,但不知道它的最新修订号,甚至不知道它的路径:

    1. 从 Repo Browser 在根目录上执行“显示日志”
    2. 点击“显示全部”(在日志对话框的底部)
    3. 在过滤器文本框中输入文件名(在日志对话框的顶部)

    这将只显示文件被添加/修改/删除的那些修订。 这是您的文件历史记录。

    请注意,如果通过删除其父文件夹之一来删除文件,则日志中不会有“已删除”条目(因此 mjy 的解决方案将不起作用)。在这种情况下,它在过滤日志中的最新条目将与其删除时的内容相对应。

    【讨论】:

    • 蛮力并不总是那么糟糕。尤其是在大型回购中。
    • +1 仅用于 UI 解决方案。命令行很棒,而且一切都很好,但它并不总是无一例外的最佳答案。尤其是当您在无法控制的环境中工作,并且无法通过命令行轻松访问 SVN 时。
    • 请注意,上面的答案是针对 TortoiseSVN GUI 的。
    【解决方案6】:
    svn log -v | grep -B50 YourDeletedFileName
    

    将为您提供路径和修订。在 git 中(也检查重命名):

    git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
    

    【讨论】:

    • -B50 有什么作用?我可以使用 svn log 和 grep 使用此处的提示轻松获取文件列表,但我似乎根本无法轻松显示修订号,因为它们显示在不同的行上。我尝试了 B50 的东西,但它对我来说似乎并没有那么神奇。
    • 它输出数学行和上面的 50 行以防其他人正在阅读此内容。
    【解决方案7】:

    如果您不知道已删除文件的路径,那么您可以在其他过于繁重的svn log 命令中搜索

    svn log --search <deleted_file_or_pattern> -v
    

    该命令可能会像没有搜索选项那样对服务器造成很大的影响,但至少其他相关资源(包括您的眼球)会有所缓解,因为这会告诉您该文件的修订版本删除。然后,您可以按照其他提示进行操作(主要使用相同的svn log 命令,但已经在定义的路径上)。

    【讨论】:

    • svn log --search _test2.php -v ... svn:无效选项:--search ... :(
    【解决方案8】:

    除了达斯汀的回答,如果你只是想检查内容,而不是检查出来,在他的例子中你可以这样做:

    $ git show 8d4a1f^:slosh.tac
    

    the : 将修订版和该修订版中的路径分开,有效地要求特定修订版的特定路径。

    【讨论】:

    • 啊,非常正确。我曾经这样做是非常非常困难的。 :)
    【解决方案9】:

    使用这个命令:

    svn log -v | awk '/^r[0-9]+/ { rev = $1; }; / D .*filename_escaped_for_regex/ { print rev" "$2; };'
    

    这将列出曾经删除任何与该模式匹配的文件的所有修订。 也就是说,如果您正在搜索文件 README,则会找到并列出所有 /src/README/src/README.first/some/deeply/hidden/directory/READMENOT

    如果您的文件名包含斜杠(路径)、点或其他特殊的正则表达式字符,请不要忘记转义它们以避免不匹配或错误。

    【讨论】:

      【解决方案10】:

      发帖者实际上在这里提出了 3 个问题:

      1. 如何在 Subversion 中查看已删除文件的历史记录?
      2. 如何在 Subversion 中查看已删除文件的内容?
      3. 如何在 Subversion 中恢复已删除的文件?

      我在这里看到的所有答案都是针对问题 2 和 3。

      问题1的答案是:

      svn log http://server/svn/project/file@1234
      

      您仍然需要获取文件上次存在时间的修订号,此处其他人已明确回答。

      【讨论】:

        【解决方案11】:

        啊,因为我正在学习使用 Bazaar,所以我尝试过。如果没有成功,您目前似乎无法log and annotate removed files... :-(

        试过了:

        > bzr log -r 3 Stuff/ErrorParser.hta
        bzr: ERROR: Path does not have any revision history: Stuff/ErrorParser.hta
        

        但奇怪的是(幸运的是)我可以做到:

        > bzr cat -r 3 Stuff/ErrorParser.hta
        

        和:

        > bzr diff -r 2..3 Stuff/ErrorParser.hta
        

        正如上面的错误中所建议的:

        > bzr log -v | grep -B 1 ErrorParser
        

        (根据需要调整-B (--before-context) 参数)。

        【讨论】:

          【解决方案12】:

          您需要指定一个修订版。

          svn log -r <revision> <deleted file>
          

          【讨论】:

          • 这给出了一个错误。示例:svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' 找不到路径
          • 你确定它在那个版本中存在吗?您必须指定文件实际存在的版本。
          • 查看 Bert Huijben 的答案,了解 -r37428 和将 @37428 添加到 SVN URL 之间的奇怪差异。
          【解决方案13】:

          如果您想查看文件在重命名之前的历史记录,那么您可以使用 a comment here 中提到的

          git log --follow -- current_file_name
          

          【讨论】:

            【解决方案14】:

            我自己想要一个答案。尝试以下操作以仅输出来自 svn log 的删除。

            svn log --stop-on-copy --verbose [--limit <limit>] <repo Url> | \
            awk '{ if ($0 ~ /^r[0-9]+/) rev = $0 }
              { if ($0 ~ /^ D /) { if (rev != "") { print rev; rev = "" }; print $0 } }'
            

            这会通过 awk 过滤日志输出。 awk 缓冲它找到的每个修订行,仅在找到删除记录时输出。每个修订版只输出一次,因此修订版中的多个删除被组合在一起(如标准svn log 输出)。

            您可以指定--limit 以减少返回的记录数量。您也可以根据需要删除--stop-on-copy

            我知道有人抱怨解析整个日志的效率。我认为这是比 grep 及其“广撒网”-B 选项更好的解决方案。我不知道它是否更有效,但我想不出svn log 的替代方案。它类似于@Alexander Amelkin 的回答,但不需要特定名称。这也是我的第一个 awk 脚本,所以它可能是非常规的。

            【讨论】:

              【解决方案15】:

              假设你的文件被命名为 ~/src/a/b/c/deleted.file

              cd ~/src/a/b/c  # to the directory where you do the svn rm or svn mv command
              #cd ~/src   # if you forget the correct directory, just to the root of repository
              svn log -v | grep -w -B 9 deleted.file | head  # head show first 10 lines
              

              样本输出,在 r90440 找到它

              ...
              r90440 | user | 2017-02-03 11:55:09 +0800 (Fri, 03 Feb 2017) | 4 lines
              Changed paths:
                M /src/a/b/c/foo
                M /src/a/b/c/bar
                D /src/a/b/c/deleted.file
              

              将其复制回以前的版本(90439=90440-1)

              svn cp URL_of_deleted.file@90439 .
              

              【讨论】:

                【解决方案16】:

                您可以使用二进制搜索找到提供文件的最后一个修订版。 我为此创建了一个简单的/bin/bash 脚本:

                function svnFindLast(){
                 # The URL of the file to be found
                 local URL="$1"
                 # The SVN revision number which the file appears in (any rev where the file DOES exist)
                 local r="$2"
                 local R
                 for i in $(seq 1 "${#URL}")
                  do
                   echo "checkingURL:'${URL:0:$i}'" >&2
                   R="$(svn info --show-item revision "${URL:0:$i}" 2>/dev/null)"
                   echo "R=$R" >&2
                   [ -z "$R" ] || break
                 done
                 [ "$R" ] || {
                  echo "It seems '$URL' is not in a valid SVN repository!" >&2
                  return -1
                 }
                 while [ "$r" -ne "$R" -a "$(($r + 1))" -ne "$R" ]
                 do
                  T="$(($(($R + $r)) / 2))"
                  if svn log "${URL}@${T}" >/dev/null 2>&1
                   then
                    r="$T"
                    echo "r=$r" >&2
                   else
                    R="$T"
                    echo "R=$R" >&2
                  fi
                 done
                 echo "$r"
                }
                

                【讨论】:

                  【解决方案17】:

                  我编写了一个 php 脚本,将我所有存储库的 svn 日志复制到一个 mysql 数据库中。我现在可以对我的 cmets 或文件名进行全文搜索。

                  【讨论】:

                    猜你喜欢
                    • 2015-12-10
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-01-13
                    • 2013-03-31
                    • 2012-12-05
                    • 2021-07-28
                    • 2020-03-12
                    相关资源
                    最近更新 更多