今天我的同事差点丢失了他四天的工作成果。由于一个不正确的 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 条评论