我经常使用gitstash和gitstashpop来保存和恢复工作树中的更改。昨天,我在我的工作树中做了一些修改,这些修改是我藏起来并弹出的,然后我对工作树做了更多的修改。我想回去回顾一下昨天隐藏的更改,但gitstashpop似乎删除了对相关提交的所有引用。
我知道如果我使用git stash,那么.git/refs/stash包含用于创建stash的提交的引用。git/logs/refs/stash包含整个存储。但这些参考资料在git stash pop之后就不见了。我知道提交仍在我的存储库中,但我不知道它是什么。
有没有一种简单的方法可以恢复昨天的存储提交引用?
我最喜欢的是这一行:
git log --oneline $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )
这与这个答案基本相同,但要短得多。当然,您仍然可以添加--graph以获得树状显示。
在列表中找到提交后,使用
git stash apply THE_COMMIT_HASH_FOUND
对我来说,使用--no reflogs确实揭示了丢失的存储条目,但--unareachable(正如许多其他答案中所发现的)并没有。
在Windows下,在gitbash上运行它。
致谢:以上命令的详细信息摘自https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf
亚里士多德接受的答案将显示所有可到达的提交,包括非隐藏类提交。要过滤掉噪声:
git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
--grep="WIP on" --min-parents=3 --max-parents=3
这将只包括只有3个父提交的提交(一个存储库将有),并且其消息包含“WIP on”。
请记住,如果您用消息保存了您的存储(例如git存储保存“我新创建的存储”),这将覆盖默认的“WIP on…”消息。
您可以显示有关每次提交的更多信息,例如显示提交消息,或将其传递给git stash show:
git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
--grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
git log -1 --format=medium --color=always '{}'; echo; \
git stash show --color=always '{}'; echo; echo" | \
less -R
如果你想重新存放丢失的东西,你需要先找到丢失的东西的散列。
正如亚里斯多德·帕加尔茨所建议的那样,一个git fsck应该可以帮助你。
就我个人而言,我使用显示每次提交(可恢复提交)的log-all别名来更好地了解情况:
git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)
如果只查找“WIP on”消息,则可以执行更快的搜索。
一旦你知道你的sha1,你只需改变你的存储reflog,添加旧的存储:
git update-ref refs/stash ed6721d
你可能更希望有一个相关的消息,所以
git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d
您甚至希望将其用作别名:
restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1