Git:如何在项目提交历史中找到已删除的文件?

Ped*_*olo 1183 git

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

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

如何存在此文件的提交?

Amb*_*ber 1476

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

git log --all --full-history -- "**/thefile.*"
Run Code Online (Sandbox Code Playgroud)

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

git log --all --full-history -- <path-to-file>
Run Code Online (Sandbox Code Playgroud)

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

git show <SHA> -- <path-to-file>
Run Code Online (Sandbox Code Playgroud)

或者将其恢复到您的工作副本中:

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

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

  • 如果你不知道确切的路径怎么办?你只知道文件名? (59认同)
  • @PedroMorteRolo`git log - <path>`当你在一个从不存在文件的分支上时将没有输出.你应该总是使用`git log --all - <path>`来确保你不会错过其他分支上发生的变化.如果你有多个分支并且往往忘记路径和分支(像我一样),那么命令`git log - <path>`会非常危险,如果你和其他开发人员一起工作也很危险. (14认同)
  • @Amber,考虑在你的`git log`回答中添加`--all`(感谢[Philip](http://stackoverflow.com/a/7204977/623735)),这样人们就不会错过任何更改和文件其他分支.它会为像我这样的健忘人士带来很多悲伤. (4认同)
  • 如下面的答案所述,恢复文件应该是`git checkout <SHA> ^ - <path-to-file>`(注意^符号),因为在<SHA>提交时,文件被删除,我们需要查看先前的提交以获取已删除文件的内容 (3认同)
  • 尝试使用相对路径而不是绝对路径(如果您还没有). (2认同)
  • @priestc回答[另一个问题](http://stackoverflow.com/questions/3845234/viewing-git-history-of-moved-files) (2认同)
  • @priestc:http://stackoverflow.com/questions/6017987/is-there-a-way-in-git-to-list-all-deleted-files-in-the-repository (2认同)
  • 旁注:你的路径必须使用'/'而不是'\'花了我一整天的时间才弄明白:/ (2认同)
  • 当使用`** / thefile。*`时,通常引用它是一个好主意,例如`'** / thefile。*'`,以保护全称`*`不受外壳影响。(我不熟悉Windows外壳程序以及它们何时使用`*`,但是如果bash中当前工作目录中的意外匹配,可能会造成麻烦。) (2认同)
  • 确保将目录更改为 git 项目的根目录。使用子目录中的命令时,相对路径有问题 (2认同)

Fat*_*cet 375

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

git log --diff-filter=D --summary | grep delete
Run Code Online (Sandbox Code Playgroud)

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

git log --all -- FILEPATH
Run Code Online (Sandbox Code Playgroud)

显示已删除文件的差异

git show COMMIT_ID -- FILE_PATH
Run Code Online (Sandbox Code Playgroud)

请记住,您可以使用>like 将输出写入文件

git show COMMIT_ID -- FILE_PATH > deleted.diff
Run Code Online (Sandbox Code Playgroud)

  • 要查看提交哈希值以及删除,您可以执行`git log --diff-filter = D --summary | grep -E'delete | ^ commit\s +\S +'` (5认同)
  • 尽管我在第一步的帮助下找到了路径,但第二步会引发此错误:“未知修订版或路径不在工作树中”。 (2认同)
  • 第 2 步不返回任何内容。关于为什么会发生这种情况有什么想法吗?我的文件名是正确的。 (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` (2认同)

小智 37

无法编辑已接受的响应,因此在此处将其添加为答案,

要在git中恢复文件,请使用以下内容(注意SHA之后的'^'符号)

git checkout <SHA>^ -- /path/to/file
Run Code Online (Sandbox Code Playgroud)

  • 它在提交时将sha设为"已删除",这意味着它仍然不存在.你必须在那之前去提交才能真正得到它. (18认同)
  • @tandrewnichols只是意味着您使用了错误的提交SHA - 您希望提交您想要的文件版本*...这可能不是删除文件的版本. (6认同)
  • @Amber和你想要的提交可能是删除之前的最新提交,因此这个答案. (6认同)

Pet*_*bev 28

@Amber给出了正确答案!再补充一点,如果你不知道文件的确切路径,你可以使用通配符!这对我有用.

git log --all -- **/thefile.*
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这是为读者提供最好的结果. (6认同)
  • @PedroMorteRolo嗯.我不知道如何将现有答案复制到最高票的答案中:/这个答案本身也很有用; 一个upvote可能已经足够了? (4认同)
  • 如果文件位于项目根目录中(在 Cygwin 中测试),则不会找到该文件。 (3认同)

Cal*_*laf 28

假设您要恢复一个名为的文件MyFile,但不确定其路径(或其扩展名):

Prelim.:通过踩到git root避免混淆

一个重要的项目可能有多个具有相似或相同名称的目录.

> cd <project-root>
Run Code Online (Sandbox Code Playgroud)
  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 - full/path/to/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.`
Run Code Online (Sandbox Code Playgroud)

只需选择前面的(附加插入符号)提交:

> git checkout bd8374c^ -- full/path/to/MyFile.js
Run Code Online (Sandbox Code Playgroud)

  • 这比接受的答案要清楚得多 (6认同)
  • 对于 Windows 控制台 (cmd),在步骤 2 中使用 find 而不是 grep:`git log --diff-filter=D --summary | 找到“删除”| 找到“MyFile”`第3步,注意散列周围的引号:`git checkout“bd8374c^”--full/path/to/MyFile.js` (2认同)

Jas*_*son 19

这里繁琐的事情之一就是获取已删除文件的路径,所以我写下了一个简单的命令,dev或git用户可以传递已删除的文件名并获取历史记录:

git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all -- 
Run Code Online (Sandbox Code Playgroud)

如果有人,可以改进命令,请做.


Phi*_*ley 16

尝试使用其中一个查看器,gitk以便您可以浏览历史记录以查找该半记忆文件.(gitk --all如果所有分支都需要,请使用)

  • `--all`选项对你的答案和接受的答案都至关重要. (4认同)
  • 对于大多数项目来说,浏览历史将花费大量的时间。 (4认同)

jas*_*ard 13

如果您想查看size所有已删除文件的

以及相关的SHA

git log --all --stat --diff-filter=D --oneline
Run Code Online (Sandbox Code Playgroud)

添加 a-p|--patch也可以查看内容

git log --all --stat --diff-filter=D -p
Run Code Online (Sandbox Code Playgroud)

要缩小到任何文件,您有两个简单的选择,您可以使用路径规范,也可以通过管道连接到 grep 并搜索文件名。

使用 grep:

git log --all --stat --diff-filter=D --oneline | grep foo
Run Code Online (Sandbox Code Playgroud)

使用路径规范:

git log --all --stat --diff-filter=D --oneline -- '*foo*'
Run Code Online (Sandbox Code Playgroud)

-p|--patch如果您想查看内容,路径规范可以与 很好地配合使用:

git log --all --stat --diff-filter=D --oneline --patch -- '*foo*'
Run Code Online (Sandbox Code Playgroud)

如果您知道该文件在哪里,您可能也会喜欢这个

git log --all --full-history -- someFileName
Run Code Online (Sandbox Code Playgroud)


srg*_*hma 7

概括:

  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
Run Code Online (Sandbox Code Playgroud)