165

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

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

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

4

17 回答 17

153

当您想查看旧文件时,您真的应该知道以下之间的区别:

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可用的文件。因此此语法确实适用于已删除的文件。

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

svn cat http://server/svn/project/file@2345 -r 1234
于 2009-02-13T21:18:29.193 回答
97

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

svn log -v > log.txt

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

D <deleted file>

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

于 2008-12-30T20:17:39.030 回答
87

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

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' 来取回已删除的文件!

于 2008-12-30T20:13:24.437 回答
25

在 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

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

于 2008-12-30T20:56:32.070 回答
17

仅使用 GUI 的解决方案:

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

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

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

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

于 2010-11-29T05:08:42.017 回答
13
svn log -v | grep -B50 YourDeletedFileName

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

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
于 2012-09-06T07:27:22.983 回答
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

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

于 2012-03-23T10:19:35.250 回答
9

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

svn log --search <deleted_file_or_pattern> -v

该命令可能会像没有搜索选项一样重击服务器,但至少其他相关资源(包括您的眼球)会有所缓解,因为这会告诉您该文件在哪个修订版中被删除。然后,您可以按照其他提示(主要使用相同的svn log命令,但已经在定义的路径上)。

于 2014-11-26T12:26:19.233 回答
8

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

$ git show 8d4a1f^:slosh.tac

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

于 2008-12-30T22:22:22.320 回答
5

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

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

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

问题1的答案是:

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

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

于 2011-11-07T16:08:09.423 回答
4

啊,因为我正在学习使用Bazaar,所以我尝试过。如果没有成功,您似乎无法记录和注释当前已删除的文件...... :-(

试过:

> 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) 参数)。

于 2009-02-12T16:55:07.620 回答
1

您需要指定一个修订版。

svn log -r <revision> <deleted file>
于 2008-12-30T20:09:15.943 回答
1

如果您想在重命名文件之前查看文件的历史记录,那么如评论中所述,您可以使用

git log --follow -- current_file_name
于 2010-12-01T05:07:00.683 回答
1

我想要一个答案,我自己。尝试以下操作以仅输出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输出中)。

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

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

于 2013-01-08T16:42:25.600 回答
1

假设您的文件被命名为 ~/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 .
于 2017-03-17T02:22:20.053 回答
0

您可以使用二进制搜索找到提供文件的最后一个修订版。我/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"
}
于 2017-01-04T13:34:19.773 回答
-1

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

于 2015-03-26T17:21:40.020 回答