在 Git 存储库中查找并恢复已删除的文件

假设我在 Git 存储库中。我删除文件并提交更改。我继续工作并做出更多承诺。然后,我发现需要还原该文件。

我知道我可以使用git checkout HEAD^ foo.bar来签出文件,但是我真的不知道何时删除该文件。

  1. 找到删除给定文件名的提交的最快方法是什么?
  2. 将文件恢复到我的工作副本中最简单的方法是什么?

我希望我不必手动浏览日志,为给定的 SHA 签出整个项目,然后手动将该文件复制到我的原始项目签出中。

答案

查找影响给定路径的最后一次提交。由于该文件不在 HEAD 提交中,因此此提交必须已将其删除。

git rev-list -n 1 HEAD -- <file_path>

然后使用尖号( ^ )符号在提交之前检出版本:

git checkout <deleting_commit>^ -- <file_path>

或者在一个命令中,如果$file是有问题的文件。

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

如果您正在使用 zsh 并启用了 EXTENDED_GLOB 选项,则插入符号将不起作用。您可以改用~1

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
  1. 使用git log --diff-filter=D --summary获取所有已删除文件和已删除文件的提交;
  2. 使用git checkout $commit~1 path/to/file.ext还原删除的文件。

其中$commit是您在步骤 1 中找到的提交的值,例如e4cf499627

要恢复文件夹中所有已删除的文件,请输入以下命令。

git ls-files -d | xargs git checkout --

我遇到了这个问题,希望还原刚刚删除但尚未提交更改的文件。万一您发现自己处于这种情况下,您需要做的只是以下几点:

git checkout HEAD -- path/to/file.ext

如果您疯了,请使用git-bisect 。这是做什么的:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>

现在该运行自动化测试了。如果存在foo.bar ,shell 命令'[ -e foo.bar ]'将返回 0,否则返回 1。 git-bisect的 “运行” 命令将使用二进制搜索来自动找到测试失败的第一个提交。它从给定范围(从好到坏)的一半开始,并根据指定测试的结果将其减半。

git bisect run '[ -e foo.bar ]'

现在您处于删除它的提交。从这里开始,您可以跳回到将来,并使用git-revert撤消更改,

git bisect reset
git revert <the offending commit>

或者您可以返回一次提交并手动检查损坏:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .

基于bonyiii答案 (已提议)和我自己的有关 “ 将参数传递给 Git 别名命令 ” 的答案 ,我是新的最喜欢的别名:

git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

我丢失了一个文件,在几次提交之前被误删除了?
快:

git restore my_deleted_file

避免危机。

警告,带有 Git 2.23(2019 年第三季度)的实验命令名为git restore (!)。
因此,重命名此别名(如下所示)。


Robert Dailey 在评论中建议使用以下别名:

restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"

jegan添加了评论

为了从命令行设置别名,我使用了以下命令:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\""

如果知道文件名,这是使用基本命令的简单方法:

列出该文件的所有提交。

git log -- path/to/file

最后一个提交(最顶部)是删除文件的提交。因此,您需要还原倒数第二个提交。

git checkout {second to last commit} -- path/to/file

要恢复已删除并提交的文件:

git reset HEAD some/path
git checkout -- some/path

它已在 Git 1.7.5.4 版上进行了测试。

如果您仅进行更改并删除了文件但不提交,那么现在您分手了更改

git checkout -- .

但是删除的文件没有返回,您只需执行以下命令:

git checkout <file_path>

而且,您的文件又回来了。

我有这个解决方案

  1. 使用以下方法之一获取删除文件的提交 ID。

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* #如果您几乎不记得任何内容,建议使用
  2. 您应该得到类似以下内容:

提交 bfe68bd117e1091c96d2976c99b3bcc8310bebe7 作者:Alexander Orlov 日期:2011 年 5 月 12 日星期四 23:44:27 +0200

replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script

提交 3ea4e3af253ac6fd1691ff6bb89c964f54802302 作者:Alexander Orlov 日期:2011 年 5 月 12 日星期四 22:10:22 +0200

3 。现在使用提交 ID bfe68bd117e1091c96d2976c99b3bcc8310bebe7 做:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

由于提交 ID 引用了已删除文件的提交,因此您需要引用 bfe68b 之前的提交,您可以通过添加^1来进行引用。这意味着:在 bfe68b 之前给我提交。