在Git中,如果一个文件在提交之前被还原了,我该如何恢复已暂存的文件?

47

我尝试使用Git Tower将一项更改拉入我的存储库。在此过程中发生了冲突,我错误地点击了“全部暂存”(因为我想在解决冲突后进行提交)。当我这样做时,冲突被标记为已解决。

我想手动解决更改,所以我点击了“中止合并”,但是这样做之后,所有更改都被还原了!有没有办法找回它们呢?

3个回答

83

如果您在git中有任何已经暂存的内容,您可能可以将其找回。 (如果您只是更改了工作副本,则无法恢复它。)

首先:在继续之前备份您的存储库和工作副本。 (确保备份.git目录。)还要避免关闭此过程发生的终端或重新启动计算机。如果失败,您有机会在历史/内存中查找材料。不要运行git gc

接下来,请尝试:

git fsck --lost-found

它将打印类似以下内容:

Checking object directories: 100% (256/256), done.
Checking objects: 100% (30165/30165), done.
dangling blob 8f72c7d79f964b8279da93ca8c05bd685e892756
dangling commit 4993502a6394491190d3f4d6fb3d1e14019c2e9b

由于您丢失了暂存文件且没有提交,因此您对dangling blob条目感兴趣。

对于每个条目,运行git show <sha> - 其中一些应该是您的文件。


7
谢谢!我已经放弃了 Git 会保留任何未提交的文件这个想法。我想为那些在“lost and found”中有很多垃圾的人提供一个提示。我自己就有数百个条目,所以要找到哈希值,你也可以在 Git 目录中使用“查找文件中的内容”类似的命令,只要你记得一些你写过的文件的部分代码。 我用了find . | xargs grep 'PIECE_OF_MISSING_CODE' -sl | grep 'lost-found' - David
git show <sha> 显示的是垃圾,我的意思是有一些可识别的字符串,但其余部分都是垃圾。它是否应该以某种方式进行解码,还是就是它本身(不可用)? - jayarjo
1
谢谢。你帮我省了三周的辛苦工作。 我在想是否有一种简单的方法可以将文件恢复到它在存储库中的原始路径。 - Daniel Miranda
@jayarjo 继续搜索其他文件。这意味着你正在查看的 blob 很可能是编译代码。 - young_souvlaki
你找到文件后如何检索它? - young_souvlaki
显示剩余3条评论

38
一个非常晚的答案,可以简化(相比其他答案)使用命令行进行恢复的过程,让您更快地找出应该恢复哪些数据块。
git fsck --full --no-reflogs --unreachable --lost-found | grep blob | cut -d\  -f3 | while read in; do printf "blob: $in\n"; git cat-file -p $in; printf "\n--------------------------------\n"; done > recover.txt

这个命令将创建一个包含所有可恢复的 blob 的哈希和内容的文件。
这样,您可以轻松地搜索这个文件,并使用给定的哈希值恢复所需的 blob(使用命令git cat-file -p 8f72c7d79f964b8279da93ca8c05bd685e892756 > myFile.txt)。
免责声明:如果您有很多无法访问的 blob,这个文件可能会变得非常庞大且创建速度缓慢。
注意:使用此命令,您将检索到内容,但无法获取相应的文件名(因为树对象尚未添加到 git 对象文件夹中。只有在提交时才会完成此操作)。
如果您更喜欢使用图形界面工具并且使用的是 Windows 操作系统,您还可以使用GitExtensions来帮助恢复文件。

3
当我恢复了20多个文件时,这非常有帮助。 - John Dough
1
这真的很有帮助。有没有办法知道一个 blob 关联的文件是什么?我可以看到内容,但我只想恢复特定的文件,而且内容与其他文件相似,所以我只能通过文件名来区分。 - MasayoMusic
1
@MasayoMusic 如果文件刚被暂存(即未提交),那么无法检索文件名,因为树对象尚未添加到git对象文件夹中。这是在提交时完成的。 - Philippe
1
你现在对我来说就像上帝一样 :) 这太棒了! - Pablo
这真的救了我。你不知道我有多感激能在网上找到这个宝贵的信息。虽然需要花点功夫在生成的大文件中搜索,但这抵消了我原本以为永远丢失的几天工作重新出现的喜悦。谢谢你,互联网上的陌生人! - PilotSnipes
@PilotSnipes 不客气!我花了很多时间来制作这个命令行,并且改进了GitExtensions中的恢复功能,尽管我从未使用过它,但我知道它将为许多人节省大量时间。谢谢你的赞美之词。 - Philippe

15

针对 Alexander 给出的答案,以下是一种更简单的方法:如果你已经将修改添加到了暂存区,那么你很可能可以找回你的文件。当你运行 git add 命令时,实际上是将文件添加到 Git 的对象数据库中。在这个时候,Git 会将文件放到索引中:

改为:

补充一下 Alexander 的回答,有一个更简单的方法:如果你已经把修改加入到了暂存区,那么你很可能可以找回你的文件。当你执行git add命令时,文件实际上被添加到了 Git 对象数据库中。在这个时候,Git 会把文件放到索引中:

% git add bar.txt
% git ls-files --stage
100644 ce013625030ba8dba906f756967f9e9ca394464a 0   bar.txt
100644 6af0abcdfc7822d5f87315af1bb3367484ee3c0c 0   foo.txt

请注意,bar.txt的条目包含了该文件的对象ID。Git已将该文件添加到其对象数据库中。在这种情况下,Git已将其作为非压缩对象添加到存储库中:

% ls -Flas .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
4 -r--r--r--  1 ethomson  staff  21 14 Jun 23:58 .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a

这些文件最终将被垃圾回收(因此,确实不要显式运行 git gc)。幸运的是,默认情况下,这将在几个月内发生,而不是几天内。在这些文件被垃圾回收之前,您可以恢复它们。

最简单的方法是以交互模式下载和安装git-recover程序

% git recover -i
Recoverable orphaned git blobs:

61c2562a7b851b69596f0bcad1d8f54c400be977  (Thu 15 Jun 2017 12:20:22 CEST)
> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
> tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
> veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
> commodo consequat. Duis aute irure dolor in reprehenderit in voluptate

Recover this file? [y,n,v,f,q,?]: 

git-recover 查找对象数据库中未提交(或在索引中)的文件。 您可以在宣布其推出的博客文章中了解有关git-recover的更多信息。


1
请添加一个声明,说明这个工具和博客文章都是您的。 - jan-glx
太棒了!使用交互模式,我能够帮助我的UX团队在git merge --abort后恢复文件。为了帮助其他人,可以使用-i选项,选择“f”字母并输入您的文件名和扩展名。 - Isac Moura

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