我经常使用gitstash和gitstashpop来保存和恢复工作树中的更改。昨天,我在我的工作树中做了一些修改,这些修改是我藏起来并弹出的,然后我对工作树做了更多的修改。我想回去回顾一下昨天隐藏的更改,但gitstashpop似乎删除了对相关提交的所有引用。
我知道如果我使用git stash,那么.git/refs/stash包含用于创建stash的提交的引用。git/logs/refs/stash包含整个存储。但这些参考资料在git stash pop之后就不见了。我知道提交仍在我的存储库中,但我不知道它是什么。
有没有一种简单的方法可以恢复昨天的存储提交引用?
我刚刚构造了一个命令,帮助我找到丢失的藏匿物品:
for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less
这将列出.git/objects树中的所有对象,查找属于commit类型的对象,然后显示每个对象的摘要。从这一点来看,只需要仔细查看提交,找到合适的“WIP on work:6a9b2”(“work”是我的分支,619bb2是最近的提交)。
我注意到,如果我使用“git stash apply”而不是“git stash pop”,我就不会有这个问题,如果我用“git sash save message”,那么提交可能会更容易找到。
更新:根据内森的想法,这变得更短:
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
我无法在一个简单的命令窗口(在我的例子中是Windows7)中获得在Windows上工作的任何答案。awk、grep和Select字符串未被识别为命令。所以我尝试了一种不同的方法:
第一次运行:git fsck--无法访问| findstr“commit”将输出复制到记事本查找用start cmd/k git show替换“无法访问的提交”
将看起来像这样:
启动cmd/k git show 8506d235f935b92df65d58e7d75e9441220537a4启动cmd/k git show 44078733e1b36962571019126243782421fcd8ae启动cmd/k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1启动cmd/k git show d00aab9198e8b81d052d90720165e48b287c302e
保存为.bat文件并运行它脚本将打开一组命令窗口,显示每个提交如果你找到了你要找的,运行:git stash apply(你的哈希)
也许不是最好的解决方案,但对我来说有效
我喜欢亚里士多德的方法,但不喜欢使用GITK。。。因为我习惯于从命令行使用GIT。
相反,我接受了悬空提交,并将代码输出到DIFF文件,以便在代码编辑器中查看。
git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff
现在,您可以将生成的diff.txt文件(位于主文件夹中)加载到txt编辑器中,并查看实际代码和生成的SHA。
那就用
git stash apply ad38abbf76e26c803b27a6079348192d32f52219
如果你想重新存放丢失的东西,你需要先找到丢失的东西的散列。
正如亚里斯多德·帕加尔茨所建议的那样,一个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