查找何时在Git中删除文件


1033

我有一个n次提交的Git存储库。

我有一个我需要的文件,该文件曾经存在于存储库中,我突然寻找并想到:“哦!那个文件去哪儿了?”

是否有(一系列)Git命令会告诉我“在提交n-13时文件true_needed.txt被删除了”?

换句话说,无需查看每个单独的提交,也不知道我的Git存储库对每个文件进行了任何更改,是否可以快速找到具有该文件的最后一个提交,因此可以将其取回?



2
Pedro共享的链接回答了我的问题:当您不记得路径时如何查找已删除的文件。
Gordon Bean

Answers:


1125

git log --full-history -- [file path] 显示文件的更改,即使文件已删除也可以工作。

例:

git log --full-history  -- myfile

如果您只想查看删除文件的最后一次提交,请另外使用-1,例如, git log --full-history -1 -- [file path]

查看哪个提交删除了文件


16
可以搜索模式吗?我忘记了文件的全名=(也许有可能获得所有删除的日志?
wutzebaer14年


6
请注意,如果您使用的是PowerShell,则必须对连字符进行转义:git log'-'[文件路径]。希望这可以使其他人some之以鼻。
A. Wilson

68
我能够使用git log -- */<<filename>>.<<file extension>>不知道整个文件路径进行搜索。
汤姆·霍华德

2
@MERose方括号用作真实文件路径的占位符。
Emile Bergeron

229

简短答案:

git log --full-history -- your_file

将显示您回购记录中的所有提交,包括已触及的合并提交your_file。最后一个(顶部)是删除文件的那个。

一些解释:

--full-history这里的标志很重要。如果没有它,当您要求它提供文件日志时,Git会执行“历史简化”。这些文档只详细介绍了它的工作原理,我缺乏从源代码中找出答案所需的勇气和勇气,但是git-log文档有这么多话要说:

默认模式

将历史简化为最简单的历史,解释树的最终状态。最简单,因为如果最终结果相同,它将修剪一些侧分支(即合并具有相同内容的分支)

很明显,这与何时删除我们想要的历史记录有关,因为最简单的历史记录(说明已删除文件的最终状态)不是历史记录。是否存在一种风险,即git log--full-history将简单地声称,该文件是从未产生的?不幸的是。这是一个示范:

mark@lunchbox:~/example$ git init
Initialised empty Git repository in /home/mark/example/.git/
mark@lunchbox:~/example$ touch foo && git add foo && git commit -m "Added foo"
[master (root-commit) ddff7a7] Added foo
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foo
mark@lunchbox:~/example$ git checkout -b newbranch
Switched to a new branch 'newbranch'
mark@lunchbox:~/example$ touch bar && git add bar && git commit -m "Added bar"
[newbranch 7f9299a] Added bar
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bar
mark@lunchbox:~/example$ git checkout master
Switched to branch 'master'
mark@lunchbox:~/example$ git rm foo && git commit -m "Deleted foo"
rm 'foo'
[master 7740344] Deleted foo
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 foo
mark@lunchbox:~/example$ git checkout newbranch
Switched to branch 'newbranch'
mark@lunchbox:~/example$ git rm bar && git commit -m "Deleted bar"
rm 'bar'
[newbranch 873ed35] Deleted bar
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 bar
mark@lunchbox:~/example$ git checkout master
Switched to branch 'master'
mark@lunchbox:~/example$ git merge newbranch
Already up-to-date!
Merge made by the 'recursive' strategy.
mark@lunchbox:~/example$ git log -- foo
commit 77403443a13a93073289f95a782307b1ebc21162
Author: Mark Amery 
Date:   Tue Jan 12 22:50:50 2016 +0000

    Deleted foo

commit ddff7a78068aefb7a4d19c82e718099cf57be694
Author: Mark Amery 
Date:   Tue Jan 12 22:50:19 2016 +0000

    Added foo
mark@lunchbox:~/example$ git log -- bar
mark@lunchbox:~/example$ git log --full-history -- foo
commit 2463e56a21e8ee529a59b63f2c6fcc9914a2b37c
Merge: 7740344 873ed35
Author: Mark Amery 
Date:   Tue Jan 12 22:51:36 2016 +0000

    Merge branch 'newbranch'

commit 77403443a13a93073289f95a782307b1ebc21162
Author: Mark Amery 
Date:   Tue Jan 12 22:50:50 2016 +0000

    Deleted foo

commit ddff7a78068aefb7a4d19c82e718099cf57be694
Author: Mark Amery 
Date:   Tue Jan 12 22:50:19 2016 +0000

    Added foo
mark@lunchbox:~/example$ git log --full-history -- bar
commit 873ed352c5e0f296b26d1582b3b0b2d99e40d37c
Author: Mark Amery 
Date:   Tue Jan 12 22:51:29 2016 +0000

    Deleted bar

commit 7f9299a80cc9114bf9f415e1e9a849f5d02f94ec
Author: Mark Amery 
Date:   Tue Jan 12 22:50:38 2016 +0000

    Added bar

注意git log -- bar上面的终端转储如何导致实际上没有输出;Git正在将历史“简化”为bar从未存在的小说。git log --full-history -- bar另一方面,为我们提供了创建bar的提交和删除它的提交。

需要明确的是:这个问题不仅仅是理论上的。我只查看了文档并发现了该--full-history标志,因为git log -- some_file在我试图跟踪已删除文件的真实存储库中失败了。当您试图了解当前存在的文件如何变为当前状态时,简化历史记录有时可能会有所帮助,但是当尝试跟踪文件删除时,隐藏隐藏您关心的提交则很可能使您陷入困境。在--full-history此用例中始终使用标志。


4
请注意,这仅搜索与当前分支相关的历史记录(不是“整个回购历史记录”)...即,如果文件尚未在当前分支中删除,但已在另一个分支中,则不会找到删除提交。您必须位于已删除文件的任何分支。考虑起来也许很明显,但是起初让我很感兴趣。
Anentropic

1
这个答案有效。但是从git log输出本身来看,最后一次提交已删除文件一点也不明显。我也尝试了git log --name-status --full-history -- file_namegit log -p --stat --full-history -- file_name,但都没有明确指出该文件是在最新提交中删除的。这似乎是一个错误。
Martin_W

@Martin_ATS 对我来说,在Git 2.12.2的日志输出中mkdir somedir && cd somedir && git init && touch foo && git add foo && git commit -m "Added foo" && git checkout -b newbranch && touch bar && git add bar && git commit -m "Added bar" && git checkout master && git rm foo && git commit -m "Deleted foo" && git checkout newbranch && git rm bar && git commit -m "Deleted bar" && git checkout master && git merge newbranch && git log --name-status --full-history -- bar包含D barA bar。您没有在输出中看到这些行吗?您有什么版本?
Mark Amery

git version 2.15.1是的,您的命令序列不会报告D barA bar。也许我的问题是文件历史所特有的。我正在追踪.htaccessgitignore'ed并删除该文件的历史记录。我终于弄清楚了,然后将文件添加回去。当我包含--name-statusgit log命令中时,我看到两个A .htaccess条目(因为我在最新的提交中将其重新添加了),但是没有D .htaccess。因此,在某些情况下,即使文件已从存储库中删除,似乎git log也不会显示显式D file_name条目。
Martin_W

@Martin_ATS很好奇。我想知道是否可能将其.htaccess添加到提交X中,但又不包含在将X引入主服务器的合并提交中?这是我唯一想到的,我可能会认为应该看起来像文件已添加且从未删除,但仍然不存在。尝试找出一个MCVE,然后找出它是否是一个Git错误,如果不是,是否可以调整我的答案来处理您的情况将很有趣。
Mark Amery

84

Git日志,但是您需要在路径前添加前缀 --

例如:

dan-mac:test dani$ git log file1.txt
fatal: ambiguous argument 'file1.txt': unknown revision or path not in the working tree.

dan-mac:test dani$ git log -- file1.txt
 commit 0f7c4e1c36e0b39225d10b26f3dea40ad128b976
 Author: Daniel Palacio <danpal@gmail.com>
 Date:   Tue Jul 26 23:32:20 2011 -0500

 foo

31

我刚刚在这里添加了一个解决方案(git中是否有办法列出存储库中所有已删除的文件?),用于使用正则表达式查找已删除文件的提交:

git log --diff-filter=D --summary | sed -n '/^commit/h;/\/some_dir\//{G;s/\ncommit \(.*\)/ \1/gp}'

这将返回在some_dir(级联)目录中删除的所有内容。那里的任何sed正则表达式\/some_dir\/都可以。

OSX(由于@triplee和@keif)

git log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }

1
真好 在OS X中bash下有些不匹配:sed: 1: "/^commit/h;/\/some_dir\ ...": bad flag in substitute command: '}'
Brent Faust 2014年

@BrentFoust我无法测试这是一个小问题...尝试在末尾添加一个空格(在大括号之后但在单引号之前),在线手册页尚不清楚...
estani 2014年

很好的建议。但是在单引号之前添加空格没有帮助。右括号前也没有空格。
布伦特·浮士德2014年

1
BSD / OSX sed显然不总是使用分号作为命令分隔符。尝试将其更改为换行符,或切换到sed -n -e '/^commit/h' -e '\:/some_dir/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }
Tripleee

1
我对其进行了测试,并git log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }在OSX上为我工作。
keif '16

21

您可以找到删除了文件的最后一次提交,如下所示:

git rev-list -n 1 HEAD -- [file_path]

此处提供更多信息


11
最初认可的解决方案对我不起作用,但是这个对我有用。
尼克·海纳

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.