从 git reset --hard 中恢复?

Posted

技术标签:

【中文标题】从 git reset --hard 中恢复?【英文标题】:Recover from git reset --hard? 【发布时间】:2011-08-12 21:09:57 【问题描述】:

有没有办法从git reset --hard HEAD 恢复对工作目录的未提交更改?

【问题讨论】:

我建议取消学习 git reset。你不需要那个命令,它很危险,所以不要使用它。要将分支返回到先前的提交,git rebase -i 并删除您不想要的提交,或者 git checkout(分离头),然后 git branch -M 移动分支提示。第一个将拒绝在本地更改时运行,而后者将仅在本地修改的文件在修订之间没有差异时运行。 @Jan 我不相信。使用重置有完全正当的理由。 @spaarky21:是的,有。但git reset --hard somewhere 是少数真正危险的 git 命令之一。 @Jan 我同意,但它很危险并不意味着你不应该使用它。只知道你在做什么并小心。 :) 与Undoing a git reset --hard HEAD~1无关,因为这里原发帖人正在尝试恢复未提交的更改。 【参考方案1】:

我遇到了同样的问题,我几乎要发疯了......最初我提交了这个项目并合并了。 后来当我尝试运行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

【讨论】:

【参考方案2】:

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

我跑了git reset --hard origin/master

然后我所有的本地文件都被删除了,因为 repo 是空的。我以为一切都过去了。

这对我有用:

git reflog show
git reset HEAD@1 
git push 

【讨论】:

【参考方案3】:

信息丢失。

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

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

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

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

【讨论】:

【参考方案4】:

来自SO的回答

$ git reflog show

4b6cf8e (HEAD -> master, origin/master, origin/HEAD) HEAD@0: reset: moving to origin/master
295f07d HEAD@1: pull: Merge made by the 'recursive' strategy.
7c49ec7 HEAD@2: commit: restore dependencies to the User model
fa57f59 HEAD@3: commit: restore dependencies to the Profile model
3431936 HEAD@4: commit (amend): restore admin
033f5c0 HEAD@5: commit: restore admin
ecd2c1d HEAD@6: commit: re-enable settings app

# assuming you want to get back to 7c49ec7 (restore dependencies to the User model)

$ git reset HEAD@2

你的一天回来了! :)

【讨论】:

只是为了添加到这个答案中,这将帮助那些实际提交了通过硬重置丢弃的更改的人。 很好 - 但在我的情况下,文件完全消失了。使用git checkout HEAD@19 让我可以在分离状态下检查丢失的文件。然后使用git checkout -b new-branch-name 将它们添加回处于“附加”状态的存储库。 @NightOwl888:这里是 Git 新手,我遇到了同样的问题,我的文件仍然不见了。您能否更详细地解释一下您是如何将文件恢复为“附加”状态的(或者您能否解释一下这实际上意味着什么)?非常感谢! @user3385759 - 在 Git 中,当您在任何非分支上使用 checkout 命令时,它将进入特殊的“分离头”模式。这意味着您实际上并没有指向分支,但您可以查看在实体状态下签入的内容(在本例中为 reflog 条目)。从那个状态,你可以把它变成一个“真正的”分支,你可以使用git checkout -b new-branch-name再次返回。 Pragmatic Version Control Using Git这本书擅长用简单的语言解释Git。 ken 和 @NightOwl888 你们刚刚救了我三天的命!祝你幸福安康!【参考方案5】:

您只能恢复已丢失的暂存 (git add) 更改。

您可以通过运行此命令轻松恢复

step:1进入项目根目录,然后运行这个命令

npx git-recover

step:2输入恢复目录路径如

/Users/apple/RecoveryDirectory

您将丢失 RecoveryDirectory 中的文件

【讨论】:

【参考方案6】:

IntelliJ 有一个可通过历史命令访问的临时文件夹:

    在导航窗格中选择要从中还原文件的文件夹 双击 Shift 键 (shift-shift) 在弹出的输入框中输入Local History并回车 选择显示历史记录 现在您可以恢复到您需要的版本。

【讨论】:

【参考方案7】:

稍后您可以将 VSCode 与 ext 一起使用:GitLens - Git supercharged,因此您可以使用此扩展来反转您的代码

【讨论】:

【参考方案8】:

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

用途:

git reflog

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

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

这个技巧几次救了我的命。

你可以找到reflogHERE的文档。

【讨论】:

到目前为止,我认为这是最好最简洁的答案。使用另一个git reset --hardgit reset --hard 恢复可能看起来违反直觉,但如果您不使用--hard 开关,您将在工作区中留下条目,这些条目将有效地恢复您刚刚恢复的工作。 像魅力一样工作!上一个答案 (***.com/questions/5788037/recover-from-git-reset-hard/…) 对我不起作用。 该死,我使用了git show 67db6072093a119fef0cfe946191e09d861360d5 &gt; path-to-file,但使用git reset --hard &lt;commit-retrieved-using-reflog&gt; 会为我节省一些乏味。至少我知道下一次(我希望永远不会有下一次)。 这个答案不正确。这种方法只恢复以前提交的更改。它将无法恢复 uncommitted 更改(这就是这个问题的意义所在)。 这个解决方案对我有用。我进行了硬重置,然后当我使用 git log 时,我没有看到提交的 ID。使用 git reflog 我可以看到提交 ID【参考方案9】:

适合部分用户的答案

如果您使用的是(任何​​最近的)macOS,并且即使您不在 Time Machine 磁盘上,操作系统也会保存每小时备份,称为 local snapshots.

进入 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?

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

【讨论】:

【参考方案10】:

我今天也无意中在我的仓库中运行了git reset --hard,而今天也有未提交的更改。为了取回它,我运行了git fsck --lost-found,它将所有未引用的 blob 写入&lt;path to repo&gt;/.git/lost-found/。由于文件未提交,我在&lt;path to repo&gt;/.git/lost-found/ 内的other 目录中找到了它们。从那里,我可以使用git show &lt;filename&gt; 查看未提交的文件,复制 blob,然后重命名它们。

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

【讨论】:

我在lost-found 中得到了带有提交引用的文件。但我可以通过git show 获取内容。 只是为了节省时间#!/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 &gt; "PATH_TO_RECOVERY_DIRECTORY/$COUNTER.m" let COUNTER=COUNTER+1 done【参考方案11】:

不能通常取回未提交的更改。

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

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

git reset HEAD@1

这将恢复到之前的 HEAD

[1] vim 例如可选地存储持久撤消,eclipse IDE 存储本地历史;这些功能可能会节省您的**

【讨论】:

Eclipse 的本地历史 - 此外,由于某些更改超过 6 天,我的 Eclipse 本地历史的 Time Machine 备份!由于某种原因,由 git 管理的文件夹的 Time Machine 备份不包含我之前的更改。 幸运的是,我将 TimeMachine 设置为每小时备份一次,因此我能够从上次备份中提取文件。据我所知,它不会恢复隐藏文件,因此您应该直接从文件系统复制文件。 IDE (IntelliJ) 将更改存储在本地,从而节省了时间。感谢您的提示! git reset HEAD@1 导致 powershell 终端出错,导致 error: unknown switch ``e' 解决此问题的方法是用单引号转义大括号,如下所示:git reset 'HEAD@1' 因为花括号对 powershell 有不同的含义 Eclipse 中的本地历史记录(在我的例子中是 Intellij)节省了我恢复 unstage 更改的时间,此处为 Intellij 提供文档:blog.jetbrains.com/idea/2008/01/…【参考方案12】:

如果你使用 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 的 Local History 完美恢复了我未保存的文件,我非常感谢这个功能【参考方案13】:

如果我丢失了一些更改,我通常会这样做。

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

【讨论】:

【参考方案14】:

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

【讨论】:

【参考方案15】:

我发现git reset --hard &lt;commit&gt; 之前的所有未提交文件都会从 git 历史记录中删除。然而,我很幸运在我拔头发的整个过程中保持我的代码编辑器会话打开,我发现每个受影响的文件中的一个简单的control + z 将文件的状态返回到版本在 Git 如此热心地重置我没有特别要求的所有内容之前。 Hooray!!

【讨论】:

【参考方案16】:

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

【讨论】:

【参考方案17】:

根据定义,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 &amp;&amp; git reset --keep是你的朋友。

教你的手指不要用git reset --hard,总有一天会有回报的。

【讨论】:

所以如果git stash &amp;&amp; git reset --hard 会清除所有隐藏的内容,对吗? 不,git reset --hard 不会丢弃存储。 git stashgit reset --hard 的替代品,因为它会从您的工作树中删除未提交的更改,但它可以保护它们的安全而不是永久丢弃它们。 或者在硬重置之前提交您的更改,它们仍然会在您的本地存储库中【参考方案18】:

我刚刚做了git reset --hard 并且丢失了我所有未提交的更改。幸运的是,我使用了编辑器 (IntelliJ),并且能够从本地历史中恢复更改。 Eclipse 应该允许您这样做。

【讨论】:

以上是关于从 git reset --hard 中恢复?的主要内容,如果未能解决你的问题,请参考以下文章

恢复 git reset -hard 的误操作

恢复 git reset -hard 的误操作

git reset --hard的恢复

git reset --hard 回滚以后 以后怎么再回去?

Git 版本恢复命令reset

用SVN代替“git reset --hard”