如何在Git中恢复掉下的藏匿处?
我经常使用git stash和git stash pop来保存和恢复工作树中的更改。昨天,我在工作树中进行了一些隐藏和弹出的更改,然后对工作树进行了更多更改。我想回顾一下昨天的隐藏更改,但是git stash pop
似乎删除了对关联提交的所有引用。
我知道如果我使用git stash
,那么.git / refs / stash包含用于创建存储的提交的引用。 .git / logs / refs / stash包含整个存储。但是那些引用在git stash pop
之后消失了。我知道提交仍在我的存储库中的某个位置,但是我不知道它是什么。
有没有简单的方法来恢复昨天的隐藏提交参考?
请注意,这对我今天并不重要,因为我有每日备份,可以回到昨天的工作树中进行更改。我问,因为必须有一个更简单的方法!
解决方案
git fsck-无法访问| grep commit
应该显示sha1,尽管它返回的列表可能很大。 git show <sha1>将显示它是否是我们想要的提交。
git cherry-pick -m 1 <sha1>将合并提交到当前分支。
我刚刚构建了一个命令,该命令可以帮助我找到丢失的隐藏提交:
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:6a9bb2"(" work"是我的分支,619bb2是最近的提交)。
我注意到,如果我使用" git stash apply"而不是" git stash pop",则不会有此问题,并且如果使用" git stash save消息",则提交可能更容易找到。
更新:按照内森的想法,这变得更短了:
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
如果我们只是弹出它,并且终端仍处于打开状态,那么我们仍将在屏幕上显示" git stash pop"打印的哈希值(感谢Dolda)。
否则,我们可以在Linux和Unix上使用它找到它:
git fsck --no-reflog | awk '/dangling commit/ {print }'
对于Windows:
git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}
这将向我们显示提交图提示中的所有提交,这些不再从任何分支或者标记中引用的所有丢失的提交(包括我们曾经创建的每个隐藏提交)都将位于该图中。
找到所需的隐藏提交的最简单方法可能是将该列表传递给gitk
:
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print }' )
这将启动一个存储库浏览器,向我们显示存储库中的每个提交,无论它是否可以访问。
如果我们喜欢在控制台上使用漂亮的图形而不是单独的GUI应用程序,则可以使用git log --graph --oneline --decorate之类的东西替换那里的gitk
。
要发现隐藏提交,请查找以下形式的提交消息:
在somebranch上执行WIP:commithash一些旧的提交消息
注意:如果我们在执行git stash时没有提供消息,则提交消息将仅采用这种形式(以" WIP on"开头)。
知道所需提交的哈希之后,就可以将其作为存储应用:
git stash apply $stash_hash
或者,我们可以使用gitk
中的上下文菜单为我们感兴趣的所有无法到达的提交创建分支。之后,我们可以使用所有常规工具对它们进行任何操作。完成后,只需将那些树枝吹走即可。
只是想在接受的解决方案中提及这一新增功能。第一次尝试这种方法(也许应该已经)对我来说并不是立即显而易见的,但是要从哈希值中应用隐藏,只需使用" git stash apply":
$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219
当我不熟悉git时,这对我来说还不清楚,我尝试使用" git show"," git apply"," patch"等不同的组合。