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

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

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


当前回答

要还原已删除并提交的文件,请执行以下操作:

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

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

其他回答

您总是可以git还原删除文件的提交。(这假设删除是提交中唯一的更改。)

> 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日志显示:

> 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已恢复到存储库中。

简单而精确-

首先,获取一个最新的稳定提交,其中您可以通过-

git log 

假设您找到$commitid 1234567…,然后

git checkout <$commitid> $fileName

这将还原该提交中的文件版本。

在我们的案例中,我们在一次提交中意外删除了文件,而在一些提交之后,我们意识到了自己的错误,想要取回所有被删除的文件,而不是那些被修改的文件。

根据查尔斯·贝利的出色回答,以下是我的一句话:

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)

如果你疯了,用二分法。下面是要做的:

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平分的“run”命令将使用二进制搜索自动查找测试失败的第一个提交。它从给定范围的一半开始(从好到坏),并根据指定测试的结果将其减半。

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

现在,您在提交时删除了它。从这里,您可以跳回到未来并使用git-restore撤消更改,

git bisect reset
git revert <the offending commit>

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

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

在许多情况下,将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

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

文件现在将恢复到删除前的状态。如果你想保留它,记得将它重新提交到工作树中。