我经常使用git stash和git stash pop来保存和恢复我的工作树中的更改。昨天我在我的工作树上做了一些改变,我把它们藏起来,然后我对我的工作树做了更多的改变。我想回去回顾一下昨天隐藏的更改,但是git stash pop似乎删除了对相关提交的所有引用。
我知道如果我使用git stash,那么.git/refs/stash包含用于创建stash的提交的引用。和.git/logs/refs/stash包含整个stash。但这些参考文献都是在git stash pop之后。我知道提交仍在我的存储库的某个地方,但我不知道它是什么。
有没有一个简单的方法来恢复昨天的库存承诺参考?
请注意,今天这对我来说并不重要,因为我有每日备份,可以返回昨天的工作树来获取更改。我问是因为一定有更简单的方法!
一旦你知道你的隐藏的哈希提交下降,你可以把它的应用:
1
| git stash apply $stash_hash |
或者,你可以创建一个单独的分支,它是以
1
| git branch recovered $stash_hash |
是的,你可以在任何你想要的,所有正常的工具。当你做,只是吹走的分公司。
寻找在哈希
如果你想跟它的只有终端仍然是开放的,你将仍然有git stash pop哈希值通过屏幕上的印刷(谢谢,逼疯了)。
此外,你可以找到它在Unix或Linux,这是,Git Bash的Windows:
1
| git fsck --no-reflog | awk '/dangling commit/ {print $3}' |
使用Windows PowerShell的...or:
1
| git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];} |
这将显示您的所有邮件在您的图,这是尖的时间提交相关的任何分支或标签,每个从每个提交的提交包括隐藏的失落,你所创造的地方,将在这样的图。
easiest找到隐藏的方式提交到你想要到那可能是通gitk列表:
1
| gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) |
从国有企业...or答案emragins如果使用Windows PowerShell。
这将启动你的浏览器显示的每个库的单库所提交的,无论它是否或不可访问的。
你可以有这样的事情gitk与git log --graph --oneline --decorate替换如果你选择好的图上的图形用户界面(GUI)在单独的控制台应用程序。
现场提交到变更的提交信息,看这个表:
# 160 160 # &;&;& # 160 160;和#;在制品在线somebranch:一些老commithash提交留言
注意:只有在这个信息将提交表单("在制品"开始的。)如果你没有当你做git stash供应信息。
如果您没有关闭终端,只需查看git stash pop的输出,就可以得到丢失存储的对象ID。通常看起来是这样的:
1 2 3
| $ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1) |
(注意,git stash drop也产生相同的线。)
要把那东西拿回来,只需运行git branch tmp 2cae03e,你就可以得到它作为一个分支。要将此转换为隐藏,请运行:
1 2
| git stash apply tmp
git stash |
把它作为一个分支也可以让您自由地操作它;例如,挑选它或合并它。
这就要提到除了在接受的解决方案。它不是立即明显的第一时间我想我这个方法(也许它应该被隐藏,而是利用从哈希值,就用"储藏应用":
1
| $ git stash apply ad38abbf76e26c803b27a6079348192d32f52219 |
当我是新来的蠢货,这不是我的,我是透明的,尝试不同的组合,使用`git apply"秀"、"补丁",等等。
到这一stashes列表仍然是在您的处置,但不可访问的任何更多。
1
| git fsck --unreachable | grep commit | cut -d"" -f3 | xargs git log --merges --no-walk --grep=WIP |
如果你把你的标题是隐藏的,在"半成品"-grep=WIPAT命令与结束的部分-grep=Tesselation你的消息,例如。
该命令是"半成品",因为它grepping默认是隐藏的消息是在提交表单WIP on mybranch: [previous-commit-hash] Message of the previous commit.
我只是说我是人工命令:find my隐藏的失落。
1
| 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 /对象的树,这是一locates型汇总提交的,然后每一个节目。从这一点看,这是个问题,只是通过寻找适当的承诺":一6a9bb2在制品在线工作"("工作"是我的店,是一个新619bb2提交)。
我注意到,如果我使用"储藏"的申请,而不是流行的"储藏",我也不会有这样的问题,"如果我用储藏保存的消息",然后提交,可能已被更容易找到。
更新:这与弥敦道的思想,成为短。
1
| for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less |
git fsck --unreachable | grep commit应该显示它的值列表,但回报可能是相当大的。如果它是git show 将提交显示你想要的。
将提交的git cherry-pick -m 1 合并到当前分支。
如果你想restash隐藏的失落,你需要找到你丢失的隐藏第一个哈希。
亚里士多德的pagaltzis显示git fsck应该帮助你。
我用我的个人演唱会,我的每一个log-all别名Commit(承诺做一个更好的recoverable)视图的情况:
1
| git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3) |
你可以更快的搜索,如果你的一只正在寻找"半成品"的消息。
你知道你一次你用你的隐藏的变化值添加到reflog旧藏。
1
| git update-ref refs/stash ed6721d |
你可能宁愿有一只-m相关消息
1
| git update-ref -m"$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d |
和你甚至想用这一别名:
1
| restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1 |
使用Gitk的Windows PowerShell等效项:
gitk --all $(git fsck --no-reflog | Select-String"(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })
可能有一种更有效的方法可以在一根管道中完成这项工作,但这确实可以完成这项工作。
我喜欢亚里士多德的方法,但不喜欢使用Gitk…因为我习惯于从命令行使用git。
相反,我接受了悬空提交,并将代码输出到diff文件中,以便在代码编辑器中查看。
1
| git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff |
现在,您可以将生成的diff/txt文件(它在您的主文件夹中)加载到txt编辑器中,并查看实际代码和生成的sha。
然后就用
1
| git stash apply ad38abbf76e26c803b27a6079348192d32f52219 |
在使用Git2.6.4的OSX中,我只是不小心运行了GitStash Drop,然后我通过走到下面的步骤找到了它。
如果你知道藏品的名称,那么使用:
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2
否则,您将通过以下方式从结果中手动找到ID:
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show
然后当你找到提交ID时,点击git stash apply提交ID
希望这能尽快帮助别人
为什么人们会问这个问题?因为他们还不知道或者不了解反射波。
这个问题的大多数答案给出了长命令和选项,几乎没有人会记得。所以,人们开始思考这个问题,复制粘贴他们认为他们需要的东西,然后马上就忘记了。
我建议每个有这个问题的人只检查reflog(git reflog),不要超过这个。一旦您看到了所有提交的列表,就有100种方法可以找到您要寻找的提交,并从中挑选它或创建一个分支。在这个过程中,您将了解到reflog以及各种基本git命令的有用选项。
我想向接受的解决方案中添加另一种很好的方法来完成所有的更改,当您没有可用的Gitk或没有用于输出的x时。
1 2 3
| git fsck --no-reflog | awk '/dangling commit/ {print $3}' > tmp_commits
for h in `cat tmp_commits`; do git show $h | less; done |
然后,您会得到一个接一个显示的哈希的所有差异。按"Q"进入下一个差异。
亚里士多德接受的答案将显示所有可达到的承诺,包括非藏状的承诺。过滤噪音:
1 2 3 4
| 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开启"。
请记住,如果您用一条消息(如git stash save"My newly created stash"保存了您的库存,这将覆盖默认的"WIP开启…"消息。
您可以显示关于每个提交的更多信息,例如显示提交消息,或将其传递给git stash show:
1 2 3 4 5 6 7 8
| 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 |
在一个简单的命令窗口(在我的例子中是Windows7)中,我无法得到任何在Windows上工作的答案。awk、grep和Select-string不被认为是命令。所以我尝试了另一种方法:
- 第一次运行:git fsck --unreachable | findstr"commit"。
- 将输出复制到记事本
- 查找用start cmd /k git show替换"无法到达的提交"
看起来像这样:
start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4
start cmd /k git show 44078733e1b36962571019126243782421fcd8ae
start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1
start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e
- 另存为.bat文件并运行它
- 脚本将打开一组命令窗口,显示每个提交
- 如果你找到了你要找的那个,跑:git stash apply (your hash)。
也许不是最好的解决办法,但对我很有效
通过在终端中写入此命令,可以列出所有无法到达的提交。-
检查不可访问的提交哈希-
找到藏品后再申请-
通过以下步骤恢复:
标识已删除的存储哈希代码:
Gitk--全部$(Git fsck--无reflog awk'/dangling commit/打印$3')
樱桃挑选藏品:
Git Cherry Pick-M 1$stash_hash_代码
解决冲突,如果使用:
吉特混血儿
另外,如果使用gerrit,那么提交消息可能会有问题。请在以下备选方案之前保存您的更改:
使用硬重置到上一次提交,然后重新提交此更改。
您还可以保存更改,重新设置和重新提交。
我来这里是想知道如何把藏品拿回来,不管我签了什么。特别是,我藏了一些东西,然后检查了一个旧版本,然后弹出了它,但在那个早期的时间点,藏的是一个不可操作的,所以藏的消失了;我不能只是做git stash把它推回到堆栈上。这对我很有用:
1 2 3 4 5 6 7 8 9 10 11
| $ 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 stash pop。我在做一个bisect,有一个小补丁,我想在每个bisect步骤上应用。现在我要做的是:
1 2 3 4
| $ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc. |
我无意中把Gitup应用程序中的藏匿物移除了。只需按ctrl+z撤消。
也许这对某人有帮助;)