在 Git 中,如何恢复在提交之前还原的暂存文件?

Posted

技术标签:

【中文标题】在 Git 中,如何恢复在提交之前还原的暂存文件?【英文标题】:In Git, how can I recover a staged file that was reverted prior to committing? 【发布时间】:2012-06-21 03:19:05 【问题描述】:

我试图使用 Git Tower 将更改拉入我的存储库。当我这样做时,发生了冲突,我错误地进入了所有阶段(因为我想在解决冲突后提交)。当我这样做时,冲突将自己标记为已解决。

我想手动解决更改,所以我点击了“中止合并”,但是,当我这样做时,它回滚了我的所有更改!有什么办法可以找回来吗?

【问题讨论】:

【参考方案1】:

一个非常晚的答案,可以通过让您更快地找出应该恢复哪些 blob 来简化(很多?与其他答案相比)恢复:

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,此文件可能会变得很大且创建速度很慢。

在 Windows 上,GUI GitExtensions 也有助于恢复文件。

【讨论】:

这在我恢复 20 多个文件时非常有用。 这真的很有帮助。有没有办法告诉 blob 与哪个文件相关联?我可以看到内容,但我只是试图恢复特定文件,并且内容与其他文件相似,所以我只能通过文件名来区分。 @MasayoMusic 如果文件刚刚被暂存(即未提交),则无法检索文件名,因为树对象仍未添加到 git 对象文件夹中。提交时完成。【参考方案2】:

用一个更简单的替代方案来扩展 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)。值得庆幸的是,默认情况下,这将在 个月 内发生,而不是几天。在这些文件被垃圾回收之前,您可以恢复它们。

最简单的方法是在交互模式下download and install the git-recover program:

% 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 在对象数据库中查找提交(或在索引中)的文件。您可以在the blog post announcing it 中找到有关git-recover 的更多信息。

【讨论】:

请添加披露,工具和博客文章都是您的。 太棒了。使用交互模式,我可以帮助我的 UX 团队在 git merge --abort 之后恢复文件。为了帮助其他人,使用-i,选择“f”字母并输入文件名和.extension【参考方案3】:

如果你有任何东西上演到 git,你可能应该能够取回它。 (如果您只是更改了工作副本,您将无法恢复它。)

首先:不要运行git gc。在继续之前备份您的存储库和工作副本。 (确保备份.git 目录。)同时避免关闭发生这种情况的终端,和/或重新启动——如果一切都失败了,你有机会在历史/内存中找到东西。

无论如何,首先要尝试的是:

git fsck --lost-found

它会打印类似的东西

检查对象目录:100% (256/256),完成。 检查对象:100% (30165/30165),完成。 悬垂斑点 8f72c7d79f964b8279da93ca8c05bd685e892756 悬空提交 4993502a6394491190d3f4d6fb3d1e14019c2e9b

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

为每个文件运行 git show <sha> — 其中一些应该是您的文件。

【讨论】:

谢谢!我已经放弃了 Git 保留任何未提交文件的希望。我想为那些在失物招领处有很多垃圾的人添加一个提示。我有 100 个条目,所以要找到哈希,你也可以在你的 git 目录中使用 find-in-file type 命令,只要你能记住你写的文件的某些部分。我用 find 。 | xargs grep 'PIECE_OF_MISSING_CODE' -sl | grep '失物招领' git show 显示废话,我的意思是有一些可识别的字符串,但其余的都是废话。它是要以某种方式解码,还是它本来的样子(不可用)。 我在使用git reset --hard 后几乎丢失了很多重要的更改,但被 GoLand IDE 的本地历史功能保存了 谢谢。你为我节省了 3 周的辛勤工作。我想知道是否有一种简单的方法可以将文件恢复到存储库中的原始路径。 @jayarjo 继续搜索其他文件。这意味着您正在查看的 blob 很可能是编译后的代码。

以上是关于在 Git 中,如何恢复在提交之前还原的暂存文件?的主要内容,如果未能解决你的问题,请参考以下文章

GIT:编辑旧提交中的暂存文件但保留更改

如何快速撤消 git 中的暂存和未暂存的更改?

百思不得其解,tortoisegit是把git中的暂存区概念干掉了吗

Git:将单个文件还原为其最后一次提交[重复]

如何解决git中的分歧?

Git瓷器命令将单个文件恢复为其HEAD状态但保持其分阶段状态?