检查已删除文件的历史记录


159

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

另外,如果我想恢复该文件,是否应该将svn add其恢复原样?

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

Answers:


84

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

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”找回已删除的文件!


2
您还可以通过对删除该文件的修订进行反向合并来恢复该文件。这是SVN文档中建议的过程。至于使用“ svn up”,与其说“不做”,不如说是“它不会做你想做的事情”。
rmeador

5
但是,如何查看文件的整个历史记录?
本杰明·彼得森

71
简单:使用“ -v”开关显示父文件夹的日志:您将为每个条目获得更改路径的列表。查找前面带有“ D”的名称以及已删除文件的名称。那是删除文件的修订版本。
Stefan

8
这似乎不适用于已删除的文件。如果尝试此操作,则会收到以下错误消息: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的路径请参阅@Bert Huijben在此线程下方的回复以获取可行的解决方案。
基思·帕尔默(Keith Palmer)2010年

2
如果我有一个具有100,000次提交的存储库,那么很难找到“ lastrevisionthefileexisted”!
乔恩·瓦特

151

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

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

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

第一个版本着眼于为路径,现在可作为HTTP://服务器/ SVN /项目/文件和检索文件,因为它是在修订1234(所以这个语法确实删除文件后工作)。

第二个语法获取可用的文件HTTP://服务器/ SVN /项目/文件在修订1234所以这句法DOES上删除的文件的工作。

您甚至可以结合使用这些方法来检索版本2345中作为http:// server / svn / project / file提供 但其内容与1234中相同的文件,其中包括:

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

7
加,谢谢!该线程中当前的最高响应未提及此,这太好了!
基思·帕尔默(Keith Palmer)2010年

除非使用绝对路径,否则这仍然对我失败,因为./local/file./local目录不存在时无法解析时,本地svn客户端会给出错误。对于较新版本的SVN,这可能不是问题。
Derrick Rice

2
@DerrickRice:在这种情况下,该^符号很方便:它指向存储库根目录,因此您可以说svn cat ^/local/file@REV(取决于存储库根目录和URL之间的距离)。
musiphil

原则上,这很好。对于文件夹,我收到以下:svn: E200009: Could not cat all targets because some targets are directories
巴尼

这是最好的答案。也有最高的选票。
费利佩·阿尔瓦雷斯

94

首先,找到删除文件的版本号:

svn log -v > log.txt

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

D <deleted file>

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


22
svn log -v | grep D“ file.name”
abatishchev

18
+1是第一个正确回答问题的人。如果您不知道修订在删除之前的内容,则无法查看其内容。
塞林

8
@abatishchev这将获取已删除文件的列表,但会丢弃修订信息,因此它没有用。如果您正在使用具有大量更改历史记录的大型/旧存储库,它也会很慢。
tchen 2011年

4
好,@ abatishchev的改进很棒。tchen:使用grep的-B50左右参数轻松修复,请参阅我的答案。
乔纳斯·拜斯特伦(JonasByström)2012年

2
限制非常大/旧存储库的svn log -v输出的另一个好方法是-l选项。因此,您可以使用svn log -v -l 100 | grep D“ file.name”
mindmatters 2013年

27

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

请注意,这实际上并未将文件放回修订控制中。它只是将文件以其最终状态存在时拖放到当前位置。然后,您可以添加它,或者只是检查它,或者从那时开始进行任何检查。


6
很棒的答案。唯一的问题是问题与svn有关!
JohnK '17年

16

仅使用GUI的解决方案:

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

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

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

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


蛮力并不总是那么糟。特别是在大型仓库上。
乔纳斯·拜斯特伦(JonasByström)2012年

+1(仅UI)解决方案。命令行非常棒,所有方面都很出色,但这并非总是毫无例外的最佳答案。尤其是当您在无法控制的环境中工作时,并且无法通过命令行轻松访问SVN。
Mir

请注意,以上答案仅适用于TortoiseSVN GUI。
乔治·梅伦贝格

13
svn log -v | grep -B50 YourDeletedFileName

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

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

-B50有什么作用?我可以使用这里的提示很容易地使用svn log和grep获取文件列表,但是由于它们显示在不同的行上,所以我似乎根本无法轻易显示修订号。我尝试了B50,但似乎对我来说效果并不理想。
割让

如果有其他人正在阅读此内容,它会输出数学行和上面的50行。
割让

8

除了达斯汀的答案,如果您只是想检查内容而不是将其签出,则可以在他的示例中执行以下操作:

$ git show 8d4a1f^:slosh.tac

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


啊,非常真实。我过去确实非常困难。:)
达斯汀

8

使用以下命令:

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会被发现并列出。

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


7

如果您不知道已删除文件的路径,那么您可以使用其他方法来搜索svn log

svn log --search <deleted_file_or_pattern> -v

该命令可能会像不使用搜索选项时一样重击服务器,但是至少可以缓解所涉及的其余资源(包括您的眼球),因为这将告诉您该文件的修订版本。然后,您可以遵循其他技巧(主要使用相同的svn log命令,但是已经在定义的路径上)。


svn log --search _test2.php -v... svn:无效选项:--search ... :(
thinsoldier 2015年

5

海报实际上在这里问了3个问题:

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

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

问题1的答案是:

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

您仍然需要获取文件上次存在的修订版本号,这里其他人显然会回答。


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


1

您将需要指定一个修订。

svn log -r <revision> <deleted file>

1
这给出了一个错误。示例:svn日志-r 37428 svn.example.com/deletedfile.java svn:找不到'/!svn/bc/98571/deletedfile.java'路径
Jeremy

您确定它在该修订版中存在吗?您必须指定文件实际存在的修订版本。
杰克M.09年

有关-r37428和将@ 37428添加到SVN URL之间的怪异区别,请参见Bert Huijben的答案。
dubek 2011年


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脚本,因此可能是非常规的。


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 .

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"
}

-1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.