撤销意外的git stash pop

223
我在进行一次复杂的合并之前,先将一些本地更改存储起来,然后进行了合并,但愚蠢地在运行git stash pop之前忘记提交。弹出操作导致一些问题(在大型代码库中调用了错误的方法),这些问题很难跟踪。我运行了git stash show,所以至少知道哪些文件被更改了。如果没有其他办法,我想这是一个提交更改的教训。
我的问题是:是否可能撤消弹出操作而不撤消合并?

2
在执行git stash pop之前,您不应该被允许进行提交。您是如何做到的? - C. K. Young
说实话我也不确定(这是昨天的事情)。合并没有自动提交,因为存在冲突。但之后我还是成功地运行了stash pop命令。 - nren
1
我使用的是git版本1.7.9.msysgit.0,刚刚完成了这个操作。我有未提交的文件,而stash pop命令则将所有内容合并在一起。 - PandaWood
1
在使用 Git 版本为 2.25.0.windows.1 时,我成功地将更改暂存(但尚未提交)后,运行了 “git stash pop” 命令。 - Artyom Gevorgyan
如果您在提交之前运行“stash pop/apply”并且索引了更改但丢失了它们,您可以使用“git fsck --lost-found”命令。此命令将遍历悬空的 blob(对于不熟悉 git 术语的人来说是实际文件),这些 blob 被暂存但未提交到任何地方(因此是悬空的),并将它们放置在 .git/lost-found/ 目录下,您可以使用“git show”查看它们,并查看这些是否是您要查找的文件。 - Artyom Gevorgyan
3个回答

78

尝试使用如何在Git中恢复丢失的存储,查找您弹出的stash。我认为一个stash总是有两个提交,因为它保留了索引和工作副本(所以通常索引提交将是空的)。然后使用git show查看它们的差异,并使用patch -R取消应用它们。


6
太棒了,这个命令git fsck --no-reflog | awk '/dangling commit/ {print $3}'(来自于链接)能够找到隐藏的提交记录,我通过对比手动找到了问题。谢谢! - nren
1
fsck 命令输出了一个巨大的列表。每个 SHA1 都用 git show 命令查看太繁琐了。你怎么做? - meson10
5
很遗憾,藏匿的内容被保存在 reflog 中,如果它们是真正的分支,查看弹出的藏匿历史记录将成为显而易见的方式。此外,我建议不要采用贬低投票和请求帮助的策略。 - Ben Jackson
2
我花了一点时间才弄对了。这是我的工作结果:git diff -p ${STACH_SHA1}~1 ${STASH_SHA1} | patch -R -p1;我尝试使用建议的 git show,但它的输出不适用于补丁;此外,我必须在 patch 中提供 -p1 选项以剥离 git diff 在文件前面放置的 a/..b/.. 元素,否则它将无法从仓库根目录解析路径。建议:小心谨慎,在使用补丁之前,在单独的分支中提交混乱的更改。 - acorello
我在这里的评论中找到了我的问题的答案。 stash save 确实对(索引,工作树以及如果激活了 -u 标志,则还包括未跟踪的文件)进行快照,可以使用 git log refs/stash 显示。至少在手册页中没有任何迹象表明 stash pop/apply 会执行类似的操作。 - Artyom Gevorgyan
显示剩余2条评论

43

来自git stash --help

Recovering stashes that were cleared/dropped erroneously
   If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms. However, you can try the
   following incantation to get a list of stashes that are still in your repository, but not reachable any more:

       git fsck --unreachable |
       grep commit | cut -d\  -f3 |
       xargs git log --merges --no-walk --grep=WIP

这篇回答对我在相同情境下比被采纳的回答更有帮助。


15
请注意,许多搜索“WIP”的解决方案都依赖于默认的存储消息。如果您为您的存储添加了显式消息,则它们可能不包含WIP。 - Ben Jackson
1
谢谢。我在日志命令中添加了选项--oneline以提高可读性。 - Venom
这只是帮助您找到存储提交的SHA。但是,如果与@basilikode接受的答案中的评论(git diff SHA〜1 SHA | patch -R)集成,它可以正常工作。我建议先使用path --dry-run进行检查。 - Jarek C

4
如果你的合并不是太复杂,另一个选择是:
  1. 使用 "git stash" 将所有更改(包括合并更改)移回到存储区。
  2. 再次运行合并并提交更改(不包括被丢弃存储区的更改)。
  3. 运行 "git stash pop",此时应该忽略之前合并中的所有更改,因为现在文件是相同的。
这样,你就只剩下了过早丢弃的存储区更改。

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