1. 概述
git stash
和 git 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-reflog
和 awk
,只输出我们关心的 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。