如何在项目提交历史记录中查找已删除的文件?


1274

曾几何时,我的项目中有一个文件,现在我希望能够得到它。

问题是:我不知道何时删除它以及它在哪条路径上。

如何找到该文件的提交?


类似的问题在这里:stackoverflow.com/questions/7093602/...
eckes


13
比起重复的答案,这里的答案对我来说更有用。
费利佩·阿尔瓦雷斯

5
同意...不管重复项...他们都没有出现在Google搜索中....这确实...我希望我们将不再浪费时间追赶重复项...只有时间和Google的算法可以告诉哪个问题是最好的。
蒂姆·博兰德

Answers:


1598

如果您不知道确切的路径,可以使用

git log --all --full-history -- "**/thefile.*"

如果知道文件所在的路径,则可以执行以下操作:

git log --all --full-history -- <path-to-file>

这应该显示接触该文件的所有分支中的提交列表。然后,您可以找到所需文件的版本,并显示为...

git show <SHA> -- <path-to-file>

或使用以下方法将其还原到您的工作副本中:

git checkout <SHA>^ -- <path-to-file>

请注意插入符号(^),该符号在已标识的插入符号之前得到检出,因为在<SHA>提交该文件时,我们需要查看上一个提交以获取已删除文件的内容


2
尝试使用相对路径,而不是绝对路径(如果尚未使用)。
琥珀

63
如果您不知道确切的路径怎么办?您只知道文件名吗?
priestc

17
git log -- <path>当您位于文件从未存在的分支上时,@ PedroMorteRolo 将没有输出。您应该始终使用git log --all -- <path>,以确保您不会错过其他分支上发生的更改。git log -- <path>如果您有多个分支并且倾向于忘记路径和分支(例如我),那么该命令可能非常危险,并且如果您与其他开发人员一起工作,该命令也很危险。
滚刀

4
@Amber,请考虑在您的答案中添加--all(感谢Philipgit log,以使人们不会错过其他分支上的更改和文件。这样可以使像我这样健忘的人免于很多痛苦。
滚刀

3
如在下面回答说,恢复文件应该是git checkout <SHA>^ -- <path-to-file>(注意^符号),因为在<SHA>提交的文件被删除,我们需要看一下以前的承诺得到被删除的文件的内容的时刻
kipelovets

393

获取已删除文件的列表,并复制已删除文件的完整路径

git log --diff-filter=D --summary | grep delete

执行下一个命令以查找该提交的提交ID,并复制提交ID

git log --all -- FILEPATH

显示已删除文件的差异

git show COMMIT_ID -- FILE_PATH

记住,你可以使用输出写入文件>

git show COMMIT_ID -- FILE_PATH > deleted.diff

1
尽管我在第一步的帮助下找到了路径,但第二步会抛出此错误:unknown revision or path not in the working tree
jvannistelrooy 2014年

6
要查看伴随删除的提交哈希,您可以做git log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
克里斯·米德尔顿

1
步骤2不返回任何内容。关于为什么会发生的任何想法?我的文件名正确。
Denis Kniazhev 2015年

2
要找到将三个函数合并为一个函数,请将其添加到您的.bashrc或.zshrc中:git-grep-latest(){ result_path=$(git log --diff-filter=D --summary | grep $1 | head -1 | awk '{print $4;}'); latest_commit=$(git log --all -- $result_path | head -1 | awk '{print $2;}'); git show $latest_commit -- $result_path; }现在您可以执行以下操作:git-grep-latest some_text
randomor 2015年

1
@TylerJones您可以使用管道使用linux将任何内容提供给任何东西-google linux pipes..您会喜欢的。
约翰·亨特

37

无法编辑接受的回复,因此在此处将其添加为答案,

要恢复git中的文件,请使用以下命令(注意SHA后面的'^'符号)

git checkout <SHA>^ -- /path/to/file

我不明白您为什么要^。该文件位于具有该SHA的提交中...为什么要从那里返回另一个提交?
Tony K. 2013年

19
在提交中,sha被“删除”,这意味着它仍然不存在。您必须先进行提交才能真正将其取回。
tandrewnichols 2013年

6
这只是意味着你使用了错误的提交SHA @tandrewnichols -你要提交你的文件的版本 ...这可能不是在文件被删除的版本。
2013年

6
@Amber和您想要的提交可能是删除之前的最新提交,因此此答案。
山姆·霍尔德

1
@AlexR:<SHA>~1无需使用引号将其包装即可使用。
CodeManX

37

假设您要恢复名为的文件MyFile,但不确定其路径(就此而言,其扩展名):

前提:通过进入git root避免混淆

一个不平凡的项目可能具有名称相似或相同的多个目录。

> cd <project-root>
  1. 查找完整路径

    git log --diff-filter = D --summary | grep删除| grep MyFile

    delete mode 100644 full/path/to/MyFile.js

full/path/to/MyFile.js 是您要查找的路径和文件。

  1. 确定影响该文件的所有提交

    git log --oneline --follow-完整/路径/到/MyFile.js

    bd8374c Some helpful commit message

    ba8d20e Another prior commit message affecting that file

    cfea812 The first message for a commit in which that file appeared.

  2. 检出文件

如果选择第一个列出的提交(按时间顺序选择最后一个,此处为bd8374c),将找不到该文件,因为在该提交中已将其删除。

> git checkout bd8374c -- full/path/to/MyFile.js

`error: pathspec 'full/path/to/MyFile.js' did not match any file(s) known to git.`

只需选择前面的(附加一个插入号)提交即可:

> git checkout bd8374c^ -- full/path/to/MyFile.js

3
这比接受的答案多了很多更清晰
Pouyan Khodabakhsh

对于Windows控制台(cmd),请在步骤2中使用find而不是grep:步骤2 git log --diff-filter=D --summary | find "delete" | find "MyFile"和step3,请注意哈希值周围的引号:git checkout "bd8374c^" -- full/path/to/MyFile.js
user5542121

30

@琥珀给出了正确的答案!仅此一项,如果您不知道文件的确切路径,则可以使用通配符!这对我有用。

git log --all -- **/thefile.*

4
@PedroMorteRolo嗯。我不知道将现有答案复制到投票最多的答案中的感觉:/这个答案本身也很有用;投票就足够了吗?
–Clément,

1
如果该文件位于项目根目录中(在Cygwin中测试),则不会找到该文件。
wortwart

19

下面是一个简单的命令,开发人员或git用户可以从存储库根目录传递已删除的文件名并获取历史记录:

git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all -- 

如果有人可以改善命令,请执行。


1
很好,谢谢!看来我的文件根本就不存在,但这是一个单独的问题,而且毛茸茸的多了……

如果文件似乎“丢失”,请确保从存储库根目录运行此文件
samaspin

谢谢@samaspin更新了答案。
杰森

18

尝试使用其中一种查看器,例如,gitk以便您可以浏览历史记录以查找已记住的一半文件。(gitk --all如果需要,请用于所有分支)


4
--all选项对于您的答案和接受的答案都至关重要。
滚刀

3
对于大多数项目而言,浏览历史记录将花费大量时间。
mikemaccana

5

摘要:

  1. 步骤1

您在已删除文件的历史记录中搜索文件的完整路径 git log --diff-filter=D --summary | grep filename

  1. 第2步

您可以从提交中删除文件,然后再将其删除

restore () {
  filepath="$@"
  last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk '{print $2; exit}')
  echo "Restoring file from commit before $last_commit"
  git checkout $last_commit^ -- $filepath
}

restore my/file_path

0

这是我的解决方案:

git log --all --full-history --oneline -- <RELATIVE_FILE_PATH>
git checkout <COMMIT_SHA>^ -- <RELATIVE_FILE_PATH>
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.