假设我在Git存储库中。我删除一个文件并提交更改。我继续工作,做出更多的承诺。然后,我发现我需要恢复那个文件。
我知道我可以使用git checkout HEAD^ foo.bar签出一个文件,但我不知道该文件何时被删除。
找到删除给定文件名的提交的最快方法是什么?
把那个文件放回我的工作副本最简单的方法是什么?
我希望我不必手动浏览我的日志,签出给定sha的整个项目,然后手动将该文件复制到我的原始项目签出中。
- 请注意,前面的注释回答了标题中的问题,而不是正文中的问题——其中包括查明文件何时被删除。
- 为了找到提交,删除了:git log --diff-filter=D -- path/to/file中的一个文件。
- 相关:您如何放弃Git中未分页的更改?.
- 相关:如何在提交历史记录中定位已删除的文件
- 相关:如何一次还原所有已删除的文件
- @hhh不工作,我得到错误:pathspec'./src/main/resources/file'与Git已知的任何文件都不匹配。
- @hhh-git checkout deletedFile将恢复删除deletedFile如果它被删除,但该删除尚未进行或承诺。这不是这里要问的问题;这个问题是关于如何恢复一个在许多提交之前就已提交了删除操作的文件。
查找影响给定路径的最后一次提交。由于文件不在head commit中,所以此commit必须已将其删除。
1
| git rev-list -n 1 HEAD -- <file_path> |
然后在提交之前签出版本,使用插入符号(^符号:
1
| git checkout <deleting_commit>^ -- <file_path> |
或者在一个命令中,如果$file是有问题的文件。
1
| git checkout $(git rev-list -n 1 HEAD --"$file")^ --"$file" |
如果您使用的是zsh并启用了扩展的_glob选项,插入符号将无法工作。你可以用~1代替。
1
| git checkout $(git rev-list -n 1 HEAD --"$file")~1 --"$file" |
- "狡猾的位是checkout的承诺之前,使用的后缀。谢谢。。。。。。。
- 设计的一些原则,这不会工作在zsh。。。。。。。我± git checkout $(git rev-list -n 1 HEAD"spec/Sporkfile_example.rb")^ --"spec/Sporkfile_example.rb" zsh: no matches found: b71c152d8f38dcd23ad7600a93f261a7252c59e9^切换到Bash &;它操作精细,虽然。
- 我有到使用‘出去checkout deleting _ <承诺>的<文件> _路径设计的一些原则——也许一个Windows命令行的事
- 从Windows命令行的我得到了我的错误。error: pathspec did not match any file(s) known to git.。。。。。。。该解决方案是使用的‘出去狂欢。
- "zoras zsh有它自身的扩张是"^"我相信,但是你不能使用替代的语法"~1":git checkout ~1 -- ~ x允许你指定的X commits specified之前的承诺,即1 ~是~承诺之前,2是双commits之前,等
- "你可以zoras也逃亡的 ^ ^…
- 顺便说一句,如果你使用的鱼,那是命令变得破碎和需求escapes火,或是一个bash shell脚本。
- 窗口的命令行客户端GitHub基于PowerShell responded与活体:ambiguous argument <文件> _路径:修订或未知的路径不在工作的树。用"我"来revisions从单独的路径,这类:‘出去’<命令>〔<修改>………………………],[ <文件>…………………]的"答案"(Robert Munteanu挤压我们的方法。
- "谢谢,luxton近等基因系。设计的一些原则对克拉notation不工作,而我们的方法是一种在Win7平台,但没有波浪线。
- 沃斯说,"noting单线语法不同步的工作在Windows。由于这是一个非常流行的Q &;A(和第一出入在Google),那么suggest updating的回答"说这(+的取代物^ ~ 1以上这些)。
- 什么是双层dashes,--,方法???????
- 在windows命令提示下,^字符是转义字符!因此,在cmd上,您必须键入^^来告诉cmd您需要一个单独的文本^并且不在后面转义其他内容。许多人所发生的事情是,^后面跟着一个空格。所以,cmd认为你是在逃避空间——这只会产生一个空间字符。因此,当Git得到cli参数时,它看到的是SHA1,而不是SHA1^。真的很烦人。~不是转义字符,所以这就是为什么它仍然有效的原因。(附言:如果你认为谷歌想要这个信息,请上传这个评论)
- 非常感谢,仍然无法理解为什么我们要签出提交的父级?成为提交的父级意味着什么?
- 如果在提交过程中删除了多个文件,而我想要全部删除,那该怎么办?只需重复该命令多次?
- @muhammadbabar删除所需文件的提交的父级是包含该文件的最后一次提交,因此保证是该文件的最新版本。"父"术语源于Git将提交结构化为一个树,其中提交是节点,而另一个提交之前的提交是该子节点的父节点。(康普西语101,你仍然困扰着我。)
- 对于其他想知道双破折号的人,--,它将文件名与git选项分开。除非您指定的文件名实际上看起来像git选项,否则这不是严格的死罪。
- 第三个命令是关键。谢谢!
- 请注意,您应该从存储库的根目录中运行它,否则将无法识别文件路径。我花了几分钟,直到我发现自己实际上在一个子文件夹中,所以这就是为什么它不起作用的原因。
- 第二个命令给了我一个荒谬的错误:"无法创建文件www/index.php:permission denied",尽管我以管理员身份运行控制台。
- 我得到"找不到匹配项:commithash^"。下面的答案对我有用。
使用git log --diff-filter=D --summary获取所有删除文件的承诺和删除文件的承诺;
使用git checkout $commit~1 path/to/file.ext恢复删除的文件。
其中,$commit是您在步骤1中发现的承诺值,例如e4cf499627。
- 好奇的,什么是不该~1推荐的吗?
- "汤米的波浪线的规格会给你第N次grandchild之名承诺。看到book.git-scm.com / 4 _ NEA _ treeishes.html为更多的细节。
- 这是由远的easiest和直观的方法。git log -- *PartOfMyFileName*。。。。。。。谢谢,$commit~1协会
- 我不知道那是什么$commit页,我过去HEAD代替。但是它操作的方法。
- 本厂git checkout $commit~1 filename语法设计完美的个人档案,也为整个工程和通讯录。即:恢复到全消去的图片。图片从沙:git checkout 12345~1 images12345。用于确定这个答案!!!!!!!
- "alexar $commit~1均值,你应该添加的名称的承诺。1d0c9ef6eb4e39488490543570c31c2ff594426c状的东西在$commit是。。。。。。。
- 尤金:"不"承诺的ID是一个之前的文件被删除吗?它看来,如果你把"Commit ID的文件被删除,在NEA不能找到它。
- 是的,如果你需要检查文件的内容:git show $commit~1:$path
- 这是一个伟大的答案,但美元的承诺是"超级confusing。。。。。。。:(
- "barryfruitman -我已经更新的问题到什么explain"美元的承诺"。不是的帮助吗?
要还原文件夹中所有已删除的文件,请输入以下命令。
1
| git ls-files -d | xargs git checkout -- |
- 文件通过管道传输到哪里?我看不到变化。
- 这可能是最简单的方法。它扭曲了git所做的最简单的任务是多么困难。
- 什么意思?
- git checkout--将还原中的更改。管道将用已删除文件的名称替换[文件]。
- ls-files子命令很方便,但似乎不适用于使用git rm删除的文件,即分阶段执行,更不用说提交,这是OP要求的。
我来这个问题是想恢复一个刚删除的文件,但我还没有提交更改。如果你发现自己处于这种情况,你需要做的就是:
git checkout HEAD -- path/to/file.ext
如果你疯了,用git-bisect。以下是要做的:
1 2 3
| 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的"run"命令将使用二进制搜索自动查找测试失败的第一个提交。它从给定范围的一半开始(从好到坏),并根据指定测试的结果将其切成一半。
1
| git bisect run '[ -e foo.bar ]' |
现在你已经提交了,删除了它。从这里,您可以跳回到未来,使用git-revert来撤销更改,
1 2
| git bisect reset
git revert <the offending commit> |
或者您可以返回一个承诺并手动检查损坏:
1 2 3 4
| git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar . |
- 你可以elaborate是git bisect run '[ -e foo.bar ]'???????
- 你也可以使用好的和坏的,手动的,如果它的东西,这不可能是自动检查。看在对城域网页。
- "avdgaag的git bisect runtells NEA的自动分割法的运行下面的命令字的"运行"命令,在0必须返回一good版本(见git help bisectfor details)。在'[ -e foo.bar ]'是一个标准的表达进行检测,如果不foo.barfile exists(的实施通常是在/usr/bin/[文件,这是通常的hardlinked /usr/bin/test)和单方程的标志是用来把那全是一个单一的命令行argument。。。。。。。
我最喜欢的新别名,基于Bonyiii的回答(上票),以及我自己关于"将参数传递给git alias命令"的回答:
1
| 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' |
我丢失了一个文件,几天前错误地删除了?快速:
1
| git restore my_deleted_file |
避免危机。
罗伯特·戴利在评论中提出了以下别名:
1
| restore-file = !git checkout $(git rev-list -n 1 HEAD --"$1")^ --"$1" |
杰根在评论中补充道:
For setting the alias from the command line, I used this command:
1
| 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:'restore'不是git命令。
- @结果是如果你先设置了git config alias.restore。
- 为了从命令行设置别名,我使用了以下命令: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
- @Karlmorrison你在哪个操作系统/shell中输入这个?
- 麦克(巴什)!如果你只是把一些信息放在Linux解决方案上,那就太好了^^
- @Karlmorrison不确定,但您至少可以编辑您的Git全局配置(Git-config--global--edit),并将行restore = !git checkout $(git rev-list -n 1 HEAD --"$1")^ --"$1"放入其中。
如果您知道文件名,这是使用基本命令的简单方法:
列出该文件的所有提交。
最后一次提交(最顶部)是删除文件的提交。所以您需要恢复第二次提交到最后一次提交。
1
| git checkout {second to last commit} -- path/to/file |
- 只是使用了这个解决方案,没有提交删除。不过,我可以使用最新的提交ID恢复文件。
- +10对于second to last commit澄清!
- 下一次提交到最后一次提交(上一次提交到删除)是否包含已删除文件的最新版本?从第二个到最后一个(上一个提交到删除之前的提交)可能非常过时。
- 这是我见过的第一个简单的解决方案,下次我不必回来找它。也许吧。
- @suncat2000"从第二个到最后一个"是指"上一次提交删除",与"下一个到最后一个"相同。en.wiktionary.org/wiki/PenUltimate同义词
要还原已删除并提交的文件,请执行以下操作:
1 2
| 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
- -1;这是错误的。这些命令将撤消尚未提交的删除操作(第一个命令取消删除操作,如果是分阶段执行的,第二个命令则放弃对文件的未经保存的更改),但您在此处声明,它们将恢复已提交的文件删除操作,这是不正确的,并且将失败,并出现@wisbucky's comment abov中的错误。e.
- @Markamery确实,我认为这个命令对于那些没有用git add -A显式提交已删除文件的开发人员很有效,但是恢复的文件仍然处于未提交阶段。
如果您只做了更改并删除了一个文件,但没有提交,现在您就放弃了更改。
但删除的文件没有返回,只需执行以下命令:
1
| git checkout <file_path> |
普雷斯托,你的文件回来了。
我有这个解决方案。
使用以下方法之一获取删除文件的提交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
1 2
| replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script |
commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Author: Alexander
Orlov Date: Thu May 12 22:10:22 2011
+0200
三。现在,使用提交ID bfe68bd17e1091c96d296c99b3bcc8310be7执行以下操作:
1
| git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java |
由于commit id引用的是已删除文件的commit,因此您需要在bfe68b之前引用commit,您可以通过追加^1来完成。这意味着:在bfe68b之前给我承诺。
- 这与公认的答案是相同的方法,但是有更多的方法可以找到删除提交。我仍然喜欢在公认的答案中采取的方法,但这些是很好的选择。谢谢!
- 我假设首先签出已删除的文件,然后(不更改它)提交它不会创建文件的副本。正确的?(我需要对图像进行此操作,副本会使存储库更大)
1
| git checkout /path/to/deleted.file |
- 由于已提交删除操作,因此无法工作。
- 这一个针对我的情况(无意中删除)是最直接的解决方案。
在许多情况下,将coreutils(grep、sed等)与git结合使用可能很有用。我对这些工具已经很了解了,但不太了解。如果我想搜索已删除的文件,我将执行以下操作:
1
| git log --raw | grep -B 30 $'D\t.*deleted_file.c' |
当我找到修订/提交时:
1
| git checkout <rev>^ -- path/to/refound/deleted_file.c |
就像别人在我面前说的那样。
文件现在将恢复到删除前的状态。如果你想让它一直存在,记得把它重新提交到工作树上。
git undelete path/to/file.ext
将它放入您的.bash_profile中(或打开命令shell时加载的其他相关文件):
1
| git config --global alias.undelete '!sh -c"git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -' |
然后使用:
1
| git undelete path/to/file.ext |
此别名首先检查以查找该文件存在的最后一次提交,然后从该文件存在的最后一次提交中对该文件路径执行git签出。来源
所以我必须从一个特定的提交中恢复一堆已删除的文件,并用两个命令管理它:
1 2
| 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有关,但像我这样的人使用的是诸如WebStormVCS之类的GUI工具,而不是了解git cli命令。
我右键单击包含已删除文件的路径,然后转到Git,然后单击Show History。
VCS工具显示所有的修订,我可以看到它们的所有提交和更改。
然后我选择我的朋友删除PostAd.js文件的承诺。现在见下面:
现在,我可以看到我想要删除的文件。我只需双击文件名,它就会恢复。
我知道我的答案不是Git命令,但对于初学者和专业开发人员来说,它是快速、可靠和容易的。webstorm vcs工具非常棒,非常适合与Git一起工作,不需要任何其他插件或工具。
- 这太棒了!谢谢您。对于那些使用任何JetBrains的IDES的人来说,这无疑是一个更简单的解决方案。
1 2 3 4 5
| 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 |
还原已删除的文件:
1 2 3 4 5 6
| 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 fsck --lost-found
检查每个悬空任务
git reset --hard
当我转到悬而未决的任务时,我的文件又出现了。
git status原因:
"HEAD detached from "
如果知道删除文件的提交,请运行此命令,其中是删除文件的提交:
1
| git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 -- |
管道前面的部分列出了在提交中删除的所有文件;它们都是从上一次提交中签出以恢复它们。
在我们的例子中,我们不小心在提交时删除了文件,后来又有一些提交,我们意识到了我们的错误,并希望返回所有被删除的文件,但不返回那些被修改的文件。
根据查尔斯·贝利的绝妙回答,这里是我的一句话:
1
| 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) |
简单而精确-
首先,获取一个最新的稳定提交,在该提交中-
假设你找到$commitid 1234567…,那么
1
| git checkout <$commitid> $fileName |
这将恢复提交中的文件版本。
1
| $ git log --diff-filter=D --summary | grep"delete" | sort |