从git reset --hard恢复?


457

有什么方法可以从中恢复对工作目录的未提交更改git reset --hard HEAD


49
我建议不学习git reset。您不需要该命令,它很危险,所以不要使用它。要将分支返回到先前的提交,git rebase -i并删除您不需要的提交,或git checkout(分离头部),然后git branch -M移动分支提示。第一个将拒绝运行本地更改,而第二个仅在本地修改的文件在两个修订版本之间没有差异的情况下运行。
Jan Hudec

11
@Jan我不相信。有完全正当的理由使用重置。
spaaarky21

4
@ spaaarky21:是的,有。但是git reset --hard somewhere是少数几个真正危险的git命令之一。
2013年

5
@Jan我同意,但是危险并不意味着您不应该使用它。只知道您在做什么,并要小心。:)
spaaarky21 2013年

3
撤消git reset --hard HEAD〜1无关,因为此处原始发布者试图恢复未提交的更改。

Answers:


474

通常,您无法取回未提交的更改。

以前分阶段进行的更改(git add)应该可以从索引对象中恢复,因此,如果这样做了,请使用git fsck --lost-found来查找与其相关的对象。(这会将对象写入.git/lost-found/目录;从那里您可以git show <filename>用来查看每个文件的内容。)

如果没有,这里的答案将是:查看您的备份。也许您的编辑器/ IDE将临时副本存储在/ tmp或C:\ TEMP下,诸如此类。[1]

git reset HEAD@{1}

这将还原到先前的HEAD

[1] vim例如,可选地存储持久性的undo,eclipse IDE存储本地历史记录;这样的功能可能会节省您的**


18
Eclipse的本地历史记录-此外,由于某些更改已超过6天,因此我的Time Machine备份了Eclipse的本地历史记录!由于某些原因,由git管理的文件夹的Time Machine备份不包含我以前的更改。
christianbrodbeck'5

2
您真是一个真正的救命助手!TextWrangler有文件备份。谢谢
Vivek Sampara

6
IDE(IntelliJ)将更改保存在本地,从而节省了一天的时间。谢谢你的提示!
progonkpa

1
哇,这太神奇了。即使您从未提交过,它也能正常工作。
Boudewijn Aasman '12

2
确实,Eclipse中的本地历史记录(在我的情况下为Intellij)节省了我恢复日新月异的变化的时间,有关Intellij的文档,请访问:blog.jetbrains.com/idea/2008/01/…–
理查德(Richard)

448

从这个回答SO

$ git reflog show
93567ad HEAD@{0}: reset: moving to HEAD@{6}    
203e84e HEAD@{1}: reset: moving to HEAD@{1}    
9937a76 HEAD@{2}: reset: moving to HEAD@{2}
203e84e HEAD@{3}: checkout: moving from master to master
203e84e HEAD@{4}: reset: moving to HEAD~1
9937a76 HEAD@{5}: reset: moving to HEAD~1
d5bb59f HEAD@{6}: reset: moving to HEAD~1
9300f9d HEAD@{7}: commit: fix-bug

# said the commit to be recovered back is on 9300f9d (with commit message fix-bug)
$ git reset HEAD@{7}

您的一天回来了!:)


24
只是要添加到此答案中,这将有助于实际上已提交通过硬重置而放弃的更改的人员。
Murki 2014年

9
很好-但就我而言,文件已完全消失。使用git checkout HEAD@{19}允许我以分离状态签出丢失的文件。然后用于git checkout -b new-branch-name将它们以“已附加”状态添加回存储库。
NightOwl888 '16

@ NightOwl888:Git新手在这里,我遇到了同样的问题,我的文件仍然不见了。您能否更详细地说明如何将文件恢复到“已附加”状态(或者您可以说明这实际上意味着什么)?非常感谢!
OhDaeSu

3
@ user3385759-在Git中,当您在非分支的对象上使用checkout命令时,它将进入特殊的“分离头”模式。这意味着您实际上并没有指向分支,但是您可以查看在实体状态下签入的内容(在这种情况下为reflog条目)。从该状态开始,您可以将其变成一个“真实”分支,您可以使用再次返回git checkout -b new-branch-name。《使用Git进行实用版本控制》一书善于用简单的术语解释Git。
NightOwl888 '16

2
是的,NomNomCameron和Jesse Adelman说了什么。我错误地认为重置将重置为我的最后一次提交。不。它消灭了一切。这个答案使我免于一两天的重新创作工作。
VeteranCoder

308

git reset --hard今天也偶然地在回购上运行,而今天也进行了未提交的更改。为了找回它,我跑了git fsck --lost-found,将所有未引用的Blob写入<path to repo>/.git/lost-found/。由于文件尚未提交,因此我在的other目录中找到了它们<path to repo>/.git/lost-found/。从那里,我可以使用看到未提交的文件git show <filename>,复制出Blob,然后重命名它们。

注意:仅当您将要保存的文件添加到索引(使用git add .)时,此方法才有效。如果文件不在索引中,则它们将丢失。


4
我只是在中带有提交引用的文件lost-found。但是我可以然后git show获取内容。
Mitar

6
只是为了节省时间的人#!/bin/bash cd PATH_TO_PROJECT/.git/lost-found/other FILES=* COUNTER = 0 for f in $FILES do echo "Processing $f file..." git show $f > "PATH_TO_RECOVERY_DIRECTORY/$COUNTER.m" let COUNTER=COUNTER+1 done
rwolst

209

是的,您可以从 git 的硬重置中恢复。

采用:

git reflog

获取提交的标识符。然后使用:

git reset --hard <commit-id-retrieved-using-reflog>

这个把戏挽救了我一生。

您可以在此处找到reflog的文档。


9
到目前为止,我认为这是最好,最简洁的答案。从git reset --hard其他位置恢复可能看起来很直观,git reset --hard但是如果您不使用该--hard开关,则将在工作区中留下可以有效还原刚刚恢复的工作的条目。
瑞安H.17年

2
奇迹般有效!先前的答案(stackoverflow.com/questions/5788037/recover-from-git-reset-hard / ...)对我不起作用。
codemax

3
这个答案是不正确的。此方法仅恢复先前提交的更改。它将无法还原未提交的更改(这是此问题的目的)。
阿德拉斯

2
该解决方案对我有用。我进行了一次硬重置,然后在使用git log时没有看到提交的ID。随着git reflog我可以看到提交ID
dboscanv

2
这对我有用。谢谢!!!!!!
RedEyed

60

在进行本地项目时,我想将其移至GitHub,然后创建一个新的存储库。当我尝试使用.gitignore将所有这些文件添加到新存储库时,我不小心添加了错误的文件,然后尝试清除它。

我跑了git reset --hard origin/master:P

然后,我的所有本地文件都删除了,因为该存储库为空。我以为一切都消失了。

这救了我一命:

git reflog show
git reset HEAD@{1} 
git push 

希望它能挽救另一条生命。


对我来说git reset HEAD@\{27\} ,谢谢!
4oby

1
我有7次提交要重置,我使用git reflog show从第一个提交进行检查,然后使用git reset HEAD@{number}
Vishwas Nahar,

38

如果您使用类似IntelliJ的工具:

在上下文菜单上,选择“本地历史记录”,然后在子菜单上单击“显示历史记录”:

项目或文件夹的本地历史记录视图向您显示最近几天完成的所有操作。在对话框下部的“操作”列中,选择要回滚的操作。[...]这样,对话框的上部显示了已更改文件的树视图。如果您只想还原已删除的文件,而不管此后进行的其他任何更改,则可以在树视图中选择文件Lost.txt,然后单击“还原”按钮。

http://blog.jetbrains.com/idea/2008/01/using-local-history-to-restore-deleted-files/

这只是让我的屁股火了!


到目前为止,这是IntelliJ用户的最佳答案!非常感谢您,这个工作非常顺利。我尝试了其他所有解决方案,但都没有一个很好的解决方案。git reflog没用,因为我没有提交更改。git fsck --lost-found适用于暂存文件,但并非所有文件都已暂存。IntelliJ的本地历史记录完美地恢复了我未保存的文件,我非常感谢此功能
Denes Papp,

30

我只是做了git reset --hard而丢失了我所有未提交的更改。幸运的是,我使用了编辑器(IntelliJ),并且能够从本地历史记录中恢复更改。Eclipse应该允许您执行相同的操作。


19

根据定义,git reset --hard它将丢弃未提交的更改,而Git无法恢复它们(您的备份系统可能会有所帮助,但Git不会)。

实际上,很少git reset --hard有什么好主意。在大多数情况下,有一个更安全的命令可以执行相同的操作:

  • 如果您要放弃未提交的更改,请使用git stash。它将保留这些更改的备份,如果您运行,它将在一段时间后过期git gc。如果您确定99.9%的人永远不需要这些更改,那么git stash对于0.1%的情况,您仍然是您的朋友。如果您100%确信,那么git stash仍然是您的朋友,因为这100%都有测量错误;-)。

  • 如果您想HEAD在历史记录中移动自己和当前分支的顶端,那么请git reset --keep成为您的朋友。它将执行与相同的操作git reset --hard,但不会放弃您的本地更改。

  • 如果您想两者都做,那git stash && git reset --keep就是您的朋友。

教您的手指不使用git reset --hard,它将一天归还。


因此,如果这样做git stash && git reset --hard会清除所有隐藏的内容,对吗?
jxramos

1
不,git reset --hard不丢弃藏匿处。从某种意义上说,它git stash是一种替代品git reset --hard,它可以从工作树中删除未提交的更改,除了可以确保它们的安全而不是永久地将其丢弃。
Matthieu Moy

或只是在进行硬重置之前提交更改,这些更改仍将在您的本地存储区中
ThaJay

11

如果您不小心硬重置了提交,请执行此操作,

git reflog show
git reset HEAD@{2} // i.e where HEAD used to be two moves ago - may be different for your case

假设HEAD@{2}是您想要回到的状态


如果您在PowerShell上执行此操作对我来说是完美的,请确保将其编写为git reset'HEAD @ {2}',否则将无法在Powershell中运行
VectorX

10

如果丢失一些更改,这通常是我要做的。

git reflog
git checkout <commit id> // now you are in where you want but you cannot push from detached branch to master
manually copy and paste changes from detached branch to master or working branch
git reset --hard HEAD // if needed
git add ... > git commit ... > git push ...

将指针移回先前的提交,但将到目前为止所做的更改保留在最新的提交签出中 git reset --soft dadada


8

信息丢失。

由于您未提交,因此您的.git从未存储此信息。因此,基本上git无法为您恢复它。

但是,如果您只是这样做git diff,则可以通过以下3个简单步骤使用终端输出来恢复。

  1. 滚动您的终端并查找的o / p git diff。将o / p保存在名为diff.patch的文件中
  2. 搜索并用制表符(\ t)替换所有7个空格和8个空格,然后保存更改。
  3. 进入您的git仓库。应用diff.patch(patch -p1 < diff.patch

您已保存!:)

注意:将数据从终端复制到文件时,请小心并清楚地看到数据是连续输出的,并且不包含任何冗余数据(由于按下了向上和向下箭头)。否则您可能会搞砸。


7

我遇到了同样的问题,我快要疯了....最初我提交了项目并合并了..后来当我尝试运行时,git push --set-upstream origin master 我遇到了这个错误

  fatal: refusing to merge unrelated histories

所以我跑了git reset --hard HEAD,它删除了一个3周的项目,但是下面的这几个命令节省了一天:

git reset HEAD@{1}         //this command unstage changes after reset
git fsck --lost-found      //I got the dangling commit fc3b6bee2bca5d8a7e16b6adaca6a76e620eca4b
git show <dangling commit something like-> fc3b6bee2bca5d8a7e16b6adaca6a76e620eca4b>
git rebase fc3b6bee2bca5d8a7e16b6adaca6a76e620eca4b

希望这可以帮助


6

您可以在完成。之后恢复提交reset --hard HEAD

利用“ git reflog”检查HEAD分支中的历史记录。

您将在此处看到您的提交及其ID。

做一个

git reset {commit Id of the commit you want to bring back}

5

如果您幸运地在另一个编辑器上打开了相同的文件(例如Sublime Text),请在这些文件上尝试使用ctrl-z。它救了我..


3

我发现很难git reset --hard <commit>从git历史记录中删除任何未提交的文件。但是,我很幸运地在拔出头发的整个过程中一直保持代码编辑器会话处于打开状态,因此我发现control + z每个受影响的文件中都有一个简单的将文件状态恢复为Git之前的版本。辛苦地重置我没有特别要求的所有内容。Hooray!!


3

如果您尝试使用以下代码:

git reflog show
# head to recover to
git reset HEAD@{1} 

由于某种原因而变得:

错误:未知开关“ e”

然后尝试HEAD@{1}用引号引起来

git reset 'HEAD@{1}'

3
 git reset HEAD@{4}

4是4步之前的更改。如果选择正确的步骤,它将显示从硬盘中删除的文件列表。然后做:

$ git reflog show

它将向您显示我们已经创建的本地提交历史记录。现在做:

$ git reset --hard 8c4d112

8c4d112是您要在此处重置硬盘的代码。让我们看一下 https://www.theserverside.com/video/How-to-use-the-git-reset-hard-command-to-change-a-commit-history以获取更多信息。


非常感谢@mohammad,它救了我。我之前看不到我的源文件,但是按照上述步骤操作,我已经能够恢复所有源文件。
Gaurav Bansal

2

正确答案。好,现在我喜欢git。:-)这是一个简单的食谱。

git log HEAD@{2}
git reset --hard  HEAD@{2}

其中“ 2”是您提交所做更改的位置的数量。就我而言,被同事和老板打扰以帮助调试某些构建问题;因此,进行了两次艰苦的重置;因此,HEAD和HEAD @ {1}被覆盖。ew,将失去我们的辛勤工作。


2

git reset --hard错误地在错误的项目上做过(我知道...)。我刚处理过一个文件,在运行命令期间和之后该文件仍处于打开状态。

即使我没有提交,也可以使用simple检索旧文件COMMAND + Z


0

这样的参考答案,

运行git reflog show之后,说您要提交9300f9d

运行git reset 9300f9d后

您可以执行git status,然后可能需要检出文件以恢复更改

git checkout-文件路径/名称


0

如果您正在使用Netbeans进行开发,请在文件选项卡和文件编辑区域之间查看。有一个“来源”和“历史记录”。在“历史记录”上,您会看到使用版本控制(git / other)进行的更改,以及本地进行的更改。在这种情况下,本地更改可以节省您的时间。


0

答案适合一部分用户

如果您使用的是(最新的)macOS,即使您不在Time Machine磁盘上,该操作系统也会保存每小时的备份,称为 本地快照

输入Time Machine并导航到丢失的文件。然后,操作系统将询问您:

The location to which you're restoring "file.ext" already contains an
item with the same name. Do you want to replace it with the one you're
restoring?

您应该能够恢复丢失的文件。


0

如果您使用相同的代码打开了IDE,请尝试对进行了更改的每个文件执行ctrl + z。git reset --hard之后,它帮助我恢复了我未提交的更改。


-3

当我们执行git reset --hard时,所有本地未提交的更改都将被删除。要恢复更改-在IDE中单击文件,将文件与本地历史记录进行比较,该记录将按日期列出更改,我们可以恢复数据。您的一天已保存!


1
这个答案重复了前面两个。
isherwood
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.