假设我在 Git 存储库中。我删除一个文件并提交该更改。我继续工作并做出更多的承诺。然后,我发现我需要在删除该文件后恢复它。
我知道我可以使用 git checkout <commit> -- filename.txt
签出文件,但我不知道该文件何时被删除。
如何找到删除给定文件名的提交?如何将该文件恢复到我的工作副本中?
git log --diff-filter=D -- path/to/file
git checkout deletedFile
将取消删除 deletedFile
如果它已被删除但删除尚未暂存或提交。这不是这里的问题所要求的;这个问题是关于如何恢复多次提交前提交删除的文件。
查找影响给定路径的最后一个提交。由于该文件不在 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"
使用 git log --diff-filter=D --summary 获取所有已删除文件和已删除文件的提交;使用 git checkout $commit~1 path/to/file.ext 恢复被删除的文件。
其中 $commit
是您在第 1 步中找到的提交的值,例如 e4cf499627
git log -- *PartOfMyFileName*
。感谢您的$commit~1
git checkout $commit~1 filename
语法适用于单个文件,也适用于整个目录。即:从 sha 12345 恢复 ./images 中所有已删除的图像:git checkout 12345~1 images
。感谢您的回答!
$commit~1
表示您应该添加提交的名称。 $commit
所在的位置类似于 1d0c9ef6eb4e39488490543570c31c2ff594426c
。
要恢复文件夹中所有已删除的文件,请输入以下命令。
git ls-files -d | xargs git checkout --
git
也变得多么困难。
ls-files
子命令很方便,但似乎不适用于已使用 git rm
删除的文件,即暂存,更不用说提交了,这是 OP 所要求的。
git
在实用性方面几乎是无与伦比的,而且学习起来也非常复杂。 git
学习曲线的很大一部分是由于用户界面不一致/不直观。就个人而言,当我学习一些困难的东西时,让我放心的一件事是看到其他(有能力的)人也很难弄清楚
我来这个问题是为了恢复我刚刚删除但尚未提交更改的文件。万一您发现自己处于这种情况,您需要做的就是以下几点:
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 .
git bisect run '[ -e foo.bar ]'
?
git bisect run
告诉 Git 通过在单词 'run' 后面运行命令来自动进行二分,其中对于 good
版本,该命令必须返回 0
(有关详细信息,请参阅 git help bisect
)。 '[ -e foo.bar ]'
是用于测试文件 foo.bar
是否存在的标准表达式(实现通常在文件 /usr/bin/[
中,通常硬链接到 /usr/bin/test
)并且单引号用于将所有内容作为单个命令行参数。
我最喜欢的新别名,基于 bonyiii 的 answer(已投票)和我自己对“Pass an argument to a Git alias command”的回答:
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 年第三季度)的出现,experimental command 名为 git restore
(!)。
所以重命名此别名(如下所示)。
Robert Dailey 提出 in the comments 以下别名:
restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"
jegan 添加 in the comments:
为了从命令行设置别名,我使用了这个命令:
git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\""
restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"
git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\""
Expansion of alias 'restore' failed; '!git' is not a git command
如果您知道文件名,这是使用基本命令的简单方法:
列出该文件的所有提交。
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 上进行了测试。
error: pathspec 'foo' did not match any file(s) known to git.
我确保文件名正确。 Git 版本 2.7.0
git add -A
提交已删除文件进行明确分期的开发人员来说效果很好,但因此恢复的文件仍处于未提交阶段。
我有 this solution。
使用以下方法之一获取文件被删除的提交的 id。 git log --grep=*word* git log -Sword git log | grep --context=5 *word* git log --stat | grep --context=5 *word* # 如果你几乎不记得任何东西,推荐你应该得到类似的东西:
commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Author: Alexander Orlov Date: Thu May 12 23:44:27 2011 +0200 replaced deprecated GWT class - gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Author: Alexander Orlov Date: 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 有关,但像我这样的人使用 GUI 工具(如 WebStorm VCS)而不是了解 Git CLI 命令。
我右键单击包含已删除文件的路径,然后转到 Git,然后单击显示历史记录。
https://i.stack.imgur.com/7302F.png
VCS 工具显示了所有修订序列,我可以看到每个修订的所有提交和更改。
https://i.stack.imgur.com/52bs4.png
然后我选择我的朋友删除 PostAd.js
文件的提交。现在见下图:
https://i.stack.imgur.com/IKZv0.png
现在,我可以看到我想要删除的文件了。我只需双击文件名即可恢复。
https://i.stack.imgur.com/UJlso.png
我知道我的答案不是 Git 命令,但对于初学者和专业开发人员来说,它快速、可靠且容易。 WebStorm VCS 工具非常棒,非常适合与 Git 一起使用,它不需要任何其他插件或工具。
git checkout /path/to/deleted.file
git 取消删除路径/到/file.ext
将其放入您的 .bash_profile(或打开命令外壳时加载的其他相关文件): git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1 )^ -- $1" -' 然后使用:git undelete path/to/file.ext
此别名首先检查以查找该文件存在的最后一次提交,然后从该文件存在的最后一次提交中对该文件路径进行 Git 签出。 Source。
在许多情况下,将 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 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-restore doc for git 2.23.0
git log --diff-filter=D --oneline -- path/to/file | cut -d ' ' -f 1
我必须从特定提交中恢复一堆已删除的文件,并使用两个命令对其进行管理:
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
清除。我需要恢复文件,然后取消暂存它们。我有数百个文件要恢复,并且像在其他示例中那样为每个文件手动输入内容会太慢。
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
在我们的案例中,我们不小心删除了提交中的文件,后来一些提交我们意识到我们的错误,并希望取回所有被删除的文件,而不是那些被修改的文件。
根据查尔斯·贝利的出色回答,这是我的单线:
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)
如果您知道删除文件的提交,请运行以下命令,其中 <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
文件/文件夹在过去的某些提交中被删除:
使用 git log --diff-filter=D --summary 获取删除文件/文件夹的提交的详细信息;使用 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>
您可以使用以下命令获取工作树中所有已删除文件的列表。
$ git ls-files --deleted
如果已提交删除,则找到它发生的提交,然后从该提交中恢复文件。
$ git rev-list -n 1 HEAD -- <file>
$ git checkout <commit>^ -- <file>
如果您正在寻找要恢复的文件的路径,以下命令将显示所有已删除文件的摘要。
$ git log --diff-filter=D --summary
我也有这个问题,使用下面的代码将以前的文件检索到本地目录:
git checkout <file path with name>
下面的例子对我有用:
git checkout resources/views/usaSchools.blade.php
您可以签出已删除的文件:
git checkout
输出
D index.html
要恢复它:
git restore index.html
如果您删除了多个文件并且需要恢复所有使用:
git restore .
https://i.stack.imgur.com/mvzJ0.gif
$ git log --diff-filter=D --summary | grep "delete" | sort
为了使用 Git 恢复所有已删除的文件,您还可以执行以下操作:
git checkout $(git ls-files --deleted)
其中 git ls-files --deleted
列出所有已删除的文件,而 git checkout $(git command)
恢复参数中的文件列表。
± git checkout $(git rev-list -n 1 HEAD "spec/Sporkfile_example.rb")^ -- "spec/Sporkfile_example.rb" zsh: no matches found: b71c152d8f38dcd23ad7600a93f261a7252c59e9^
我改用 bash &不过效果很好。error: pathspec <filename> did not match any file(s) known to git.
。解决方案是使用 git bash。git checkout <deleting-commit>~1 -- <file-path>
~X 允许您在指定提交之前指定 X 次提交,所以 ~1 是之前的提交, ~2 是之前的两次提交,等等^
字符是转义字符!因此,在 cmd 上,您必须输入^^
来告诉 cmd 您想要一个文字 ^ 并且您不会在它之后转义其他内容。许多人遇到的情况是^
后面跟着一个空格。所以 cmd 认为你正在转义空间——这只会产生一个空格字符。因此,当 git 获取 cli 参数时,它会看到SHA1
和 notSHA1^
。这真的很烦人。~
不是转义字符,所以它仍然有效。 (PS。如果您认为 googlers 会想要此信息,请点赞此评论)