1. 概述

git stashgit stash pop 是我们临时保存和恢复工作目录更改的常用命令。在本教程中,我们将学习如何恢复一个被删除的 stash

2. 暂存工作目录更改

以一个实际例子说明:假设你 fork 了一个 Git 仓库并克隆到本地(如 https://github.com/eugenp/tutorials),然后你对 README.md 文件做了一些修改:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

此时可以使用 git stash 将这些更改暂存起来:

$ git stash
Saved working directory and index state WIP on master: a8088442db Updated pom.xml

再次执行 git status,你会发现工作目录已恢复干净状态:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

3. 恢复 Stash 并获取提交 Hash

接下来我们看看如何恢复 stash 并找到对应的提交 hash。

3.1. 恢复 Stash 到工作目录

使用 git stash pop 可以将 stash 内容应用回工作目录:

$ git stash pop
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (59861637f7b599d87cb7a1ff003f1b0212e8908e)

⚠️ 注意:git stash pop 不仅会恢复 stash 内容,还会自动删除 stash 的引用记录,这就是为什么我们后续需要 hash 来恢复它的原因。

3.2. 终端未关闭时获取 Hash

如果终端还没关,可以直接从 git stash pop 的输出中看到对应的 hash:

Dropped refs/stash@{0} (59861637f7b599d87cb7a1ff003f1b0212e8908e)

这个 hash 就是我们要找的 stash 提交 hash。

3.3. 终端关闭后如何找回 Hash

即使终端关闭了,也可以通过 git fsck 命令查找“悬空”提交(dangling commit):

$ git fsck --no-reflog
Checking object directories: 100% (256/256), done.
Checking objects: 100% (302901/302901), done.
dangling commit 59861637f7b599d87cb7a1ff003f1b0212e8908e

这样就能看到刚刚被删除的 stash 提交 hash。

4. 恢复被删除的 Stash

正常情况下,我们不会再去恢复已经被 pop 掉的 stash。但如果你在恢复后执行了 git reset --hard HEAD,那这些更改就会被彻底删除。这时候,如果你还想恢复,就需要用到 hash。

4.1. 使用 Hash 恢复 Stash

有了 hash 后,可以用 git stash apply 恢复:

$ git stash apply 59861637f7b599d87cb7a1ff003f1b0212e8908e
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

✅ 成功恢复了之前被删除的 stash 内容!

4.2. 查找所有悬空提交 Hash

如果你不知道具体 hash,可以通过以下命令列出所有悬空的 commit:

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

这个命令组合使用了 --no-reflogawk,只输出我们关心的 hash。

5. 小结 ✅

  • git stash pop 会恢复并删除 stash 记录
  • 被删除的 stash 会变成一个 dangling commit
  • 可以通过 git fsck 找到 hash,再用 git stash apply <hash> 恢复
  • 如果你执行了 git reset --hard,记得及时恢复 stash,否则会丢失更改

📌 小贴士:如果你经常用 stash,建议改用 git stash apply 而不是 pop,避免误删 stash。


原始标题:How to Recover a Dropped Stash in Git