今天我的同事几乎丢失了他四天的工作成果。 由于一个不正确的 git 命令,他丢弃了他在 stash 中保存的更改。 在这个令人难过的事件之后,我们寻找一种方法来尝试恢复他的工作……我们做到了!
首先警告:当您实现一个大的功能时,将其分成小块并定期提交。 长时间不提交您的更改不是一个好主意。
现在我们已经解决了这个问题,让我们演示如何恢复意外从 stash 中删除的更改。
我的示例存储库,只有一个源文件 main.c,看起来像这样

opensource.com
它只有一个提交,即初始提交

opensource.com
我们的文件的第一个版本是

opensource.com
我将开始编写一些代码。 对于这个例子,我不需要做一个大的更改,只需要一些东西放入 stash,所以我将只添加一个新行。 git-diff 输出应该是

opensource.com
现在,假设我想从远程存储库中拉取一些新的更改,但我还没有准备好提交我的更改。 相反,我决定 stash 它,拉取远程存储库的更改,然后将我的更改应用回 master。 我执行以下命令将我的更改移动到 stash
git stash
使用 git stash list 查看 stash,我可以看到我的更改在那里

opensource.com
我的代码在一个安全的地方,并且 master 分支是干净的(我可以使用 git status 检查这一点)。 现在我只需要拉取远程存储库的更改,然后将我的更改应用到 master 上,我就应该完成了。
但我不小心执行了
git stash drop
这会删除 stash,而不是
git stash pop
这本应在从堆栈中删除 stash 之前应用它。 如果我再次执行 git stash list,我可以看到我从 stash 中删除了我的更改,而没有将其应用到 master 分支。 天啊! 谁能帮帮我?
好消息:git 没有删除包含我的更改的对象; 它只是删除了对它的引用。 为了证明这一点,我使用 git-fsck 命令,该命令验证数据库中对象的连接性和有效性。 这是我在存储库上执行 git-fsck 命令后的输出

opensource.com
使用 --unreachable 参数,我要求 git-fsck 向我显示无法访问的对象。 正如您所见,它没有显示无法访问的对象。 在我删除 stash 上的更改后,我执行了相同的命令,并收到了不同的输出

opensource.com
现在有三个无法访问的对象。 但哪个是我的更改? 实际上,我不知道。 我必须通过执行 git-show 命令来查看每个对象来搜索它。

opensource.com
找到了! ID 95ccbd927ad4cd413ee2a28014c81454f4ede82c 对应于我的更改。 现在我找到了丢失的更改,我可以恢复它了! 一种解决方案是将 ID 检出到新分支或直接应用提交。 如果您有包含您的更改的对象的 ID,您可以决定将更改再次放在 master 分支上的最佳方法。 对于此示例,我将使用 git-stash 再次将提交应用到我的 master 分支。
git stash apply 95ccbd927ad4cd413ee2a28014c81454f4ede82c
另一个要记住的重要事项是 git 定期运行其垃圾收集器。 在执行 gc 后,您将无法再使用 git-fsck 查看无法访问的对象。
本文最初发表在作者的博客上,并经许可转载。
6 条评论