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

171
如果我在Subversion中删除了一个文件,如何查看它的历史记录和内容?如果我尝试对不存在的文件执行svn catsvn log,它会报告文件不存在。
此外,如果我想恢复该文件,我只需要使用svn add重新添加它吗?
(我特别询问了Subversion,但我也想了解Bazaar、Mercurial和Git如何处理这种情况。)
17个回答

158

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

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

7
谢谢!这个主题目前排名最靠前的回复没有提到这一点,这太好了! - Keith Palmer Jr.
除非我使用绝对路径,否则这仍然对我失败了,因为当./local目录不存在时,我的本地svn客户端无法解析./local/file而出现错误。这可能不是较新版本的SVN的问题。 - Derrick Rice
2
在这种情况下,^符号很方便:它指的是存储库根目录,因此您可以说svn cat ^/local/file@REV(取决于存储库根目录和URL之间的距离)。 - musiphil
这是最好的答案。票数也最高。 - Felipe Alvarez
这就是你要找的答案。我不确定为什么被接受的答案获得了那么多票或被接受,因为据我所知它并不起作用。 - wytten
显示剩余2条评论

100

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

svn log -v > log.txt

那么就查看 log.txt(作为一个SVN非专业人士,我不知道更好的方式)中是否有一行包含

的内容。

D <deleted file>

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


23
SVN日志 -v | grep D "file.name": 查询SVN日志中带有"file.name"并标记为删除(D)的记录。 - abatishchev
21
作为第一个正确回答问题的人,我给你点赞。如果您不知道修订前的内容,则无法查看其内容。 - Cerin
9
@abatishchev 这个命令可以获取已删除的文件列表,但是它会丢弃修订信息,因此它没有用处。而且如果你正在处理具有大量更改历史记录的大型/旧存储库,它的速度很慢。 - tchen
4
很好,加上@abatishchev的改进非常棒。tchen提到可以使用-grep参数-B50或类似方法轻松解决,详见我的回答。 - Jonas Byström
2
另一个限制非常大/旧的存储库的svn log -v输出的好方法是使用-l选项。因此,您可以使用svn log -v -l 100 | grep D "file.name"。 - mindmatters

86

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

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


3
您可以通过对删除文件时的版本进行反向合并来恢复文件,这是SVN文档中推荐的过程。至于使用 "svn up",问题不在于“不要这样做”,而在于“它无法实现您想要的效果”。 - rmeador
5
我该如何查看文件的完整历史记录呢? - Benjamin Peterson
71
简单说明:使用‘-v’开关显示父文件夹的日志,您将得到每个条目更改路径的列表。找到前面带有'D'的条目并找到您所删除文件的名称。那就是该文件被删除的版本。 - Stefan
9
这似乎不适用于已删除的文件。如果我尝试这样做,我会收到以下错误消息: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 Jr.
5
如果我的代码库有10万个提交,"lastrevisionthefileexisted"并不容易找到! - Jon Watte
显示剩余2条评论

23

在 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
请注意,这并没有实际将文件放回版本控制中。它只是将文件以其最终状态的形式丢到当前位置。然后,您可以从那一点开始添加它,检查它或者进行其他操作。

8
好的,我会尽力进行翻译。以下是需要翻译的内容:精彩的回答。唯一的问题是这个问题是关于svn的! - JohnK
由于该帖子没有试图回答明确涉及Subversion的原始问题,考虑对其进行投票,以便有机会将其删除。 - Arseni Mourzenko
由于原始问题中有这样的评论,即“(我特别问的是关于Subversion的,但我也想听听Bazaar、Mercurial和Git如何处理这种情况)”,因此对其进行贬低评分是不公平的。 - undefined

17

仅使用 GUI 的解决方案:

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

  1. 从“存储库浏览器”中对根目录执行“显示日志”
  2. 点击“显示全部”(在日志对话框底部)
  3. 将文件名输入筛选文本框中(在日志对话框顶部)

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

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


暴力破解并不总是最好的选择,特别是在大型代码库中。 - Jonas Byström
1
UI解决方案加1分。 命令行很好,但并非总是最佳答案。特别是当你在一个你不控制且没有轻松的命令行访问SVN的环境中工作时。 - Mir
3
请注意,上述答案是针对TortoiseSVN GUI而言的。 - Georg Muehlenberg

14
svn log -v | grep -B50 YourDeletedFileName

这将为你提供路径和版本。在Git中(还会检查重命名):

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

“-B50”是什么意思?我可以使用这里的技巧轻松地使用svn log和grep获取文件列表,但是由于它们显示在不同的行上,因此似乎无法轻松地显示修订号。我尝试了B50,但对我来说似乎并没有那么神奇。 - cedd
它输出匹配的行以及上面的50行,以防其他人阅读此内容。 - cedd

10

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

svn log --search <deleted_file_or_pattern> -v

这个命令可能会像没有搜索选项时一样使服务器繁忙,但是至少其他相关资源(包括你的眼睛)会有所减轻,因为它会告诉你该文件在哪个版本中被删除。然后,您可以遵循其他提示(主要是使用相同的svn log命令,但已在定义路径上执行)。


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

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等所有文件。
如果您的文件名包含斜杠(路径),点或其他特殊的正则表达式字符,请不要忘记对其进行转义,以避免不匹配或错误。

9
除了Dustin的回答,如果你只想检查内容而不是检出它,在他的示例中,你可以这样做:
$ git show 8d4a1f^:slosh.tac

冒号(:)在一个版本和该版本中的路径之间进行分隔,有效地要求在特定版本中获取特定路径。


啊,非常正确。我曾经以非常非常困难的方式做过那件事。 :) - Dustin

5
海报实际上在这里问了3个问题:
  1. 如何查看Subversion中已删除文件的历史记录?
  2. 如何查看Subversion中已删除文件的内容?
  3. 如何在Subversion中恢复已删除的文件?
我看到的所有答案都是针对第2和第3个问题的。
对于第1个问题的答案是:
svn log http://server/svn/project/file@1234

您仍需要获取文件上次存在时的修订版本号,其他人已经清楚地回答了这个问题。

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