我经常使用gitstash和gitstashpop来保存和恢复工作树中的更改。昨天,我在我的工作树中做了一些修改,这些修改是我藏起来并弹出的,然后我对工作树做了更多的修改。我想回去回顾一下昨天隐藏的更改,但gitstashpop似乎删除了对相关提交的所有引用。

我知道如果我使用git stash,那么.git/refs/stash包含用于创建stash的提交的引用。git/logs/refs/stash包含整个存储。但这些参考资料在git stash pop之后就不见了。我知道提交仍在我的存储库中,但我不知道它是什么。

有没有一种简单的方法可以恢复昨天的存储提交引用?


当前回答

我喜欢亚里士多德的方法,但不喜欢使用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 stash apply”:

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

当我刚接触git时,我并不清楚这一点,我尝试了“git show”、“git apply”、“patch”等不同的组合。

我想在已接受的解决方案中添加另一个好方法,以在您没有gitk可用或没有X输出时完成所有更改。

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

for h in `cat tmp_commits`; do git show $h | less; done

然后,您将获得这些哈希值的所有差异。按“q”进入下一个差异。

我来这里的目的是,不管我签了什么,都要如何真正拿回藏起来的东西。特别是,我藏了一些东西,然后检查了一个旧版本,然后打开了它,但在更早的时间点,这个藏的东西是不可用的,所以这个藏的就消失了;我不能只做git stash把它推回到堆栈上。这对我有用:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

回想起来,我应该使用git stash apply而不是git stashpop。我在做二等分,在每一个二等分步骤上都有一个小补丁。现在我正在做这件事:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.

不完全是一个获取隐藏的答案,但如果目标是获取未提交的更改,这些更改首先被隐藏,然后被弹出到另一个分支中,但这两种更改都适用,并按以下方式完成:

在分支中进行更改(_a)暂存从branch_a生成branch_b应用git存储

然后,要将未提交的更改还原到branch_a:

git结帐分支agit合并分支bgit重置HEAD~1

亚里士多德接受的答案将显示所有可到达的提交,包括非隐藏类提交。要过滤掉噪声:

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