繁体   English   中英

如何在 Git 存储库中查找和恢复已删除的文件?

[英]How do I find and restore a deleted file in a Git repository?

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

我知道我可以使用git checkout <commit> -- filename.txt签出文件,但我不知道该文件何时被删除。

  1. 如何找到删除给定文件名的提交?
  2. 如何将该文件恢复到我的工作副本中?

查找影响给定路径的最后一个提交。 由于该文件不在 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 上进行了测试。

我有这个解决方案

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

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | 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 之前给我提交。

如果您只进行了更改并删除了一个文件,但没有提交它,现在您与您的更改分手了

git checkout -- .

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

git checkout <file_path>

很快,你的文件又回来了。

实际上,这个问题直接与 Git 有关,但像我这样的人使用WebStorm VCS等 GUI 工具,而不是了解 Git CLI 命令。

我右键单击包含已删除文件的路径,然后转到 Git,然后单击Show History

在此处输入图像描述

VCS 工具显示了所有修订序列,我可以看到每个修订的所有提交和更改。

在此处输入图像描述

然后我选择我的朋友删除PostAd.js文件的提交。 现在见下图:

在此处输入图像描述

现在,我可以看到我想要删除的文件了。 我只需双击文件名即可恢复。

在此处输入图像描述

我知道我的答案不是 Git 命令,但对于初学者和专业开发人员来说,它快速、可靠且容易。 WebStorm VCS 工具非常棒,非常适合与 Git 一起使用,它不需要任何其他插件或工具。

git checkout /path/to/deleted.file

git undelete path/to/file.ext

  1. 将其放入您的.bash_profile (或打开命令外壳时加载的其他相关文件):

     git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
  2. 然后使用:

     git undelete path/to/file.ext

此别名首先检查以查找该文件存在的最后一次提交,然后从该文件存在的最后一次提交中对该文件路径进行 Git 签出。 来源

在许多情况下,将coreutils (grep、sed 等)与 Git 结合使用会很有用。 我已经非常了解这些工具,但 Git 不太了解。 如果我想搜索已删除的文件,我会执行以下操作:

git log --raw | grep -B 30 $'D\t.*deleted_file.c'

当我找到修订/提交时:

git checkout <rev>^ -- path/to/refound/deleted_file.c

就像其他人在我之前所说的那样。

该文件现在将恢复到删除之前的状态。 如果您想保留它,请记住将其重新提交到工作树。

我必须从特定提交中恢复一堆已删除的文件,并使用两个命令对其进行管理:

git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- 
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(注意每个命令末尾的尾随空格。)

这些文件已添加到 .gitignore 文件中,然后使用git rm清除。 我需要恢复文件,然后取消暂存它们。 我有数百个文件要恢复,并且像在其他示例中那样为每个文件手动输入内容会太慢。

我有同样的问题。 在不知不觉中,我创建了一个悬空提交

列出悬空提交

git fsck --lost-found

检查每个悬空提交

git reset --hard <commit id>

当我移动到悬空提交时,我的文件重新出现。

git status的原因:

“HEAD detached from <commit id where it detached>”

找到删除文件的提交:

git log --diff-filter=D --oneline -- path/to/file | cut -f -d ' '

样本输出:

4711174

从 Git 2.23 开始,实际上有一个restore命令。 仍处于试验阶段,但为了恢复您在提交中删除的内容(在本例中为 4711174),您可以输入:

git restore --source=4711174^ path/to/file

请注意提交 id 之后的^ ,因为我们想从删除文件之前的提交中恢复某些内容。

--source参数告诉restore命令在哪里寻找要恢复的文件,它可以是任何提交,甚至是索引。

请参阅: git 2.23.0 的 git-restore 文档

在我们的案例中,我们不小心删除了提交中的文件,后来一些提交我们意识到我们的错误,并希望取回所有被删除的文件,而不是那些被修改的文件。

根据查尔斯·贝利的出色回答,这是我的单线:

git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)
user@bsd:~/work/git$ rm slides.tex
user@bsd:~/work/git$ git pull 
Already up-to-date.
user@bsd:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory

恢复已删除的文件:

user@bsd:~/work/git$ git checkout
D       .slides.tex.swp
D       slides.tex
user@bsd:~/work/git$ git checkout slides.tex 
user@bsd:~/work/git$ ls slides.tex
slides.tex

如果您知道删除文件的提交,请运行以下命令,其中<SHA1_deletion>是删除文件的提交:

git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --

管道前面的部分列出了提交中删除的所有文件; 它们都是从以前的提交中签出以恢复它们。

要获得最好的方法,请尝试一下。


首先,找到删除文件的提交的提交 ID。 它将为您提供删除文件的提交摘要。

git log --diff-filter=D --summary

git checkout 84sdhfddbdddf~1

注意: 84sdhfddbddd是您的commit id

通过这个,您可以轻松恢复所有已删除的文件。

加分点:以下方法确实适用于文件/文件夹甚至从您的垃圾箱或回收站中被删除的情况。

文件/文件夹已从工作树中删除但尚未提交:

I. 如果您还没有索引(git add)您的更改,您可以恢复目录的内容:

git restore -- path/to/folder_OR_file

二、 如果删除已编入索引,则应首先重置:

git reset -- path/to/folder_OR_file

然后执行, git restore path/to/folder_OR_file

文件/文件夹在过去的某些提交中被删除:

  1. 使用git log --diff-filter=D --summary获取删除文件/文件夹的提交的详细信息;
  2. 使用git checkout $commit~1 path/to/folder_OR_file恢复已删除的文件/文件夹。 其中$commit是您在步骤 1 中找到的提交的 sha 值,例如 c7578994

简单而精确——

首先,通过以下方式获取最新的稳定提交,其中包含该文件 -

git log 

假设你找到 $commitid 1234567...,那么

git checkout <$commitid> $fileName

这将恢复该提交中的文件版本。

你总是可以git revert删除文件的提交。 这假设删除是提交中的唯一更改。

> git log
commit 2994bda49cd97ce49099953fc3f76f7d3c35d1d3
Author: Dave <dave@domain.com>
Date:   Thu May 9 11:11:06 2019 -0700

    deleted readme.md

如果您继续工作,并且后来意识到您不想提交删除提交,您可以使用以下方法恢复它:

> git revert 2994bd

现在git log显示:

> git log
Author: Dave <dave@domain.com>
Date:   Thu May 9 11:17:41 2019 -0700

    Revert "deleted readme"

    This reverts commit 2994bda49cd97ce49099953fc3f76f7d3c35d1d3.

并且readme.md已恢复到存储库中。

如果您只想在 master 中恢复相同的文件,这是我找到的最简单的解决方案:

git checkout master -- path/to/File.java

我也有这个问题,使用下面的代码将以前的文件检索到本地目录:

git checkout <file path with name>

下面的例子对我有用:

git checkout resources/views/usaSchools.blade.php

如果尚未提交删除,则以下命令将恢复工作树中已删除的文件。

$ git checkout -- <file>

您可以使用以下命令获取工作树中所有已删除文件的列表。

$ git ls-files --deleted

如果已提交删除,则找到它发生的提交,然后从该提交中恢复文件。

$ git rev-list -n 1 HEAD -- <file>
$ git checkout <commit>^ -- <file>

如果您正在寻找要恢复的文件的路径,以下命令将显示所有已删除文件的摘要。

$ git log --diff-filter=D --summary

您可以签出已删除的文件:

git checkout

输出

D       index.html

要恢复它:

git restore index.html

如果您删除了多个文件并且需要恢复所有使用:

git restore .

见 Gif 图像通过 git 恢复文件

$ git log --diff-filter=D --summary  | grep "delete" | sort

为了使用 Git 恢复所有已删除的文件,您还可以执行以下操作:

git checkout $(git ls-files --deleted)

其中git ls-files --deleted列出所有已删除的文件, git checkout $(git command)恢复参数中的文件列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM