不小心回滚到主分支,丢失了未提交的更改。

102

在主分支上工作时,我忘记创建新分支。对文件进行了更改,然后不小心回到了主分支,导致所有更新都丢失了。 我没有提交这些更新的文件。

我该如何找回它们?


在您的评论中提到,可以通过GitHub GUI自动保存的stash来恢复您的工作。我还没有看到GUI的操作,并一直担心丢失东西,想知道警告消息是什么样子的等等。您能否编辑您的问题,以便更清楚地说明实际发生了什么,以便我们都受益? - nealmcb
3
如果你正在使用任何JetBrains软件,请右键点击并转到“Local History > Show History”选项。从这里,您应该可以看到本地编辑历史记录列表,与Git历史记录分开。您可以选择任何版本来还原。 - sbrk
9个回答

117
如果你没有执行过 提交(commit)暂存(stash)提交阶段(staged),那么就无法恢复您所做的更改。
编辑:恢复丢失的更改。在 Mark Longair 的建议下添加此内容(评论中)。这还包括他下面答案中我认为非常有用的几个 SO 链接(*)
  • 如果你曾经 提交(commit) 了一些更改并且丢失了该提交(例如以分离状态提交),则可以使用 reflog 找到该提交。请参见此SO问题*。

  • 如果你丢失了你最后一次暂存(staged) 的更改,也可以恢复它。请参见此SO问题*。(我自己从未使用或尝试过)。

  • 如果你储藏(stashed)了一个更改,你也可以使用 popapply 恢复它。(我不确定未提交的弹出/丢弃的储藏是否也可恢复)。你可能会发现这个在 Git 中恢复丢失的储藏很有用。

如果还有其他方法可以建议,我将进一步编辑此答案以添加它们。

5
您的“私藏”提示让我找到了正确的行动方向。非常感谢。 - Trist
2
你可能想要编辑你的回答,指出如果文件只是被暂存,你也可以找回它们,因为这些文件仍然会被放入对象数据库中。请参考我的回答的第二段。 - Mark Longair
29
有些集成开发环境(IDE)会独立于源代码控制之外,跟踪本地文件的历史记录。 - Konrad Morawski
2
我曾经遇到过这种情况。当我即将失去所有希望时,我意识到我确实有一个已编译的版本,因为我运行了一次来测试新功能。然后我想到使用 ILSpy 来反编译我的 .exe 文件。虽然不是完美的,但我成功地恢复了所有更改,而不必重新开始编写所有代码。 - Pedro Corso
1
@KonradMorawski 谢谢!你救了我的一天。我不小心删除了未提交的分支。因为这些被删除的分支包含了100多个文件,数千行代码,所以我几乎疯了。这些是我一个月的工作成果。我忘记了Android Studio有本地文件历史记录。 - Wachid Susilo
显示剩余4条评论

61

两种可能的解决方法:一些集成开发环境(IDEs)如 Delphi 会记录编辑器历史,你可以在那里找到备份。
其次,如果你将本地工作目录设置在“我的文档”文件夹中,它可能已经被 Windows Home Server、Carbonite、MozyPro等自动备份软件备份了,这些软件通常是“一劳永逸”的。也许你忘记设置备份?


14
Eclipse将此功能称为“本地历史记录”。您可能甚至能够恢复尚未暂存、藏匿或提交的文件。 - Mikko Rantalainen
1
谢谢你给我提供这个想法!我能够在Dropbox网页界面中恢复“已删除”的文件!你救了我的一命。在Dropbox中恢复已删除的文件 - lyonsinbeta
4
我在Eclipse上犯了同样的愚蠢错误。我右键点击了一个已更改但没有历史记录的文件,选择“从本地历史记录中还原...”。但是当我右键点击并选择“替换为”->“本地历史记录...”时,我看到了一份更改清单。这救了我一命。希望这能帮助到其他人。 - Rahul Dabas
5
PHPStorm拥有一个版本控制系统->本地历史记录,适用于与Git无关的个别文件。 - theGreenCabbage
在 PyCharm 上使用 Command+Z 快捷键,让我成功地挽救了两天的工作成果 :) - Farhan Haider
显示剩余3条评论

42

我曾陷入同样的困境。

在进行硬重置之前,在终端上列出了更改文件的清单,进入我的编辑器(Sublime 2,不过这并不重要),打开每个文件并按下 cmd+z(撤消)一次,这有效地撤消了硬重置所做的更改,我重新获得了未提交的更改 :)


3
在VS Code中,对我也起到同样的作用。 - Monsignor
我在vscode中使用vim,按下u键无法撤销。所以,我切换了vim并按下ctrl+z来恢复一切。 - Ruthvik Vaila
这也可以在IntelliJ中完成。 - Tom Anderson

13
关键问题在于你在对文件进行更改后做了什么。如果你创建了一个包含文件新状态的提交(commit),那么你可以通过查看最近的 git reflog 条目,找到提交的 SHA1 校验和,然后使用 git branch recovered <SHA1sum>等命令从该提交创建一个新分支,这样就能够获取它们了。在这个回答中有一个这样的例子。
如果你对其中任何一个文件运行了 git add 命令来将其存入暂存区 (stage),那么你也可以将它们找回,但这需要一些额外的工作,Jakub 在这个答案中描述了如何操作。
如果你刚好运行了 git stash 命令以清除状态,那么当然可以像任何其他的 stash 一样找回它。
否则,恐怕情况并不乐观。
我希望这不会让你感到愤怒,但是,要想切换回 master 分支,你本来不应该使用任何可能导致数据丢失的命令——git checkout master 命令已经会告诉你当前已经在主分支上,并显示任何未提交的更改。 (可以说,如果存在未提交的更改,git reset --hard 应该有一个“是的,我真的想这样做”的确认提示,因为人们经常因此丢失数据。)

当我执行 git reset --hard HEAD~1 命令时,Bash 命令行没有询问我任何问题。所有未暂存和未提交的更改都被删除了,没有任何提示。 - Robert Koritnik
2
@RobertKoritnik 我认为你可能误解了我回答的最后一句话 - 我是说当 git reset --hard 时出现“您确定吗?”确认可能会丢失数据,这将是一个好功能,而不是 git 的实际操作。 - Mark Longair

3
使用reflog。 git reflog 将按时间顺序显示您所在的所有提交历史记录。
如果您通过“检出master”丢失了更改,则您可能是无头状态。 git status 将告诉您是否正在没有头部的情况下工作(以及git branch)。
无头工作并不那么糟糕(我故意这样做了很多次),但是您将更加依赖reflog。
然而,如果您没有以任何方式提交更改,则无法检索那些文件。唯一现实的可能性是,您进行了硬重置或明确强制检出。除非您确信自己舒适地丢失了数据,否则不要强制更改。
通常,在 git 中,“强制”是通过指定-f 来完成的。

谢谢您的快速回复,我在引用日志中找不到引用,但很可能是我的操作有误。我使用 GitX 找到了一个存储区,将其应用了。 - Trist

2

我做过同样的事情,不止一次。如果没有提交任何内容,git 就不知道你写了什么。即使你提交了,当回退时我也不确定 reflex 是否有帮助。


1
感谢您的快速回复,我一直在尝试使用GitHub GUI,这是在生产环境中做的愚蠢之举,但是现在已经这样了。看起来在我造成损坏之前,它执行了一个“stash”。 - Trist
@Trist 这就是解决我的方法。我差点要对GitHub咒骂,因为它让人很容易在不提交的情况下切换分支(且GUI界面中没有可见的存储函数),直到看到你的评论。git stash apply拯救了这一天。 - John

1
大多数IDE都有“本地历史”功能,包括所有JetBrains产品。您还可以在所有受影响的文件中尝试使用ctrl+Z。如果万不得已,您可以检查Time Machine备份/任何其他定期运行的备份软件。

0
如果你在IntelliJ中工作,右键点击你的父文件夹。在菜单中,选择本地历史记录 > 显示历史记录。IntelliJ中的本地历史记录 在这里,你将找到你想要还原的版本。

0
在VS Code中,使用命令面板打开“本地历史:查找要恢复的条目”,然后搜索要恢复的文件的路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接