This question具有相同的标题,但不相同的问题。这个问题实际上是在问“放弃git stash pop的结果”。这个问题实际上是
换句话说
// in branch foo
git stash
git checkout bar
git stash pop # ERROR. I didn't want to pop on top of bar, lots of conflicts
git stash undo-pop # NEED COMMAND TO PUT STASH AND LOCAL FILES BACK AS THEY WERE
git checkout foo
git stash pop
在输入git stash pop
之前,有没有办法让所有东西回到状态?换句话说,实际上 UNDO pop并将隐藏的东西放回藏匿处,并将本地文件恢复到我输入git stash pop之前的状态。
这也不是How to recover a dropped stash in Git?的欺骗行为虽然在某些情况下可能会有所帮助
答案 0 :(得分:12)
在您的示例中,要恢复到<wchar.h>
之前的状态,请使用:
git stash pop
这种形式的git reset --hard bar
命令将索引和的状态恢复到git reset
分支的头部。
由于您在第一个bar
上存在冲突,因此存储保留在存储堆栈顶部。
从那里,您可以再次git stash pop
和git checkout foo
。
答案 1 :(得分:2)
Greg Hewgill's answer是正确的(并且赞成,并且OP应该接受它)但是这里有几个额外的警告,以防有人想以更一般的方式使用答案。让我们首先看一下使用的特定命令序列:
git stash git checkout bar git stash pop # ERROR ... lots of conflicts
现在,让我们列出警告:
git stash pop
失败很重要。 (格雷格已经注意到这一点。)git stash --keep-index
后,你没有对工作树进行任何更改。git stash
命令成功,因此 it 可能已对您的工作树进行了更改 - 事实上,它必须已经这样做,git checkout
失败了 - 但你的工作树仍然是“干净的”,正如pop
所说的那样。这是最后一点,git status
会(在尝试git status
之前)告诉您工作树是git stash pop
,这是关键。如果您在clean
之前或之后对工作树进行了更改,那么您将遇到更多麻烦。
因为你没有做这些事情,git checkout bar
才是答案。
通常,git reset --hard
做两次提交。一个保存当前的索引,另一个保存当前的工作树。 1 这些提交在某些方面略显特殊;最重要的是他们在没有分支。 2 提交后,git stash
正常运行git stash
。 3
git reset --hard
步骤的作用是使索引和工作树与当前提交匹配。也就是说,我们已经将(整个)索引和(整个跟踪部分)工作树保存在存储中;所以当前git reset --hard
提交和索引之间的不同,可以重新设置为相同;在HEAD
提交和工作树之间的不同,可以重新设置为相同。
在HEAD
之后,索引和工作树都是“干净的”,因为git reset
会说:它们都匹配git status
提交。然后,您可以HEAD
其他分支,因为您没有未保存的工作。然后,您可以尝试git checkout
,甚至git stash apply
,将您的更改“移动”到另一个分支。
当失败时 - 就像在这种情况下 - 藏匿处仍保存在已保存的藏匿处中。当前索引和工作树现在充满了合并冲突。如果你运行git stash pop
,Git将像往常一样重新设置索引和工作树以匹配git reset --hard
提交,这样你就会回到{{{}后的同样情况。 1}}步骤。由于您没有未保存的工作(您的已保存的工作仍在隐藏提交中),您可以在这里。
(如果你 有未保存的工作,HEAD
步骤会通过尝试合并隐藏的工作树更改来破坏未保存的工作。这很难撤消,一般。)
1 虽然git checkout
通常会进行两次提交,但如果您使用git stash apply
或git stash
运行,则会使三次提交。我喜欢将这些称为--all
(索引),--include-untracked
(工作树)和i
(无标记文件)提交。
使用w
或u
时,--all
或--include-untracked
步骤不只是save
:它还会运行push
删除进入第三次提交的任何内容(未跟踪的文件或未跟踪的包含忽略的文件)。在应用这样的存储之前,您可能需要重复此git reset --hard
工作,这非常棘手且烦人。
稍后,当您运行git clean
时,Git将(尝试)应用git clean
提交(如果存在)。它将始终(尝试)应用git stash apply
提交。如果您给它u
标志,它将(尝试)仅应用w
提交 。在许多版本的i
中存在一些小错误,围绕着整个“单独索引恢复”的东西。它们往往会影响想要使用--index
和git stash
标志的用户,例如预提交挂钩。
请注意--keep-index
只是--index
:也就是说,尝试应用存储,然后如果Git认为git stash pop
进展顺利,那么{{1}存储。我发现最好首先使用git stash apply && git stash drop
,以避免丢弃隐藏即使 Git认为它进展顺利,因为Git和我有时不同意“进展顺畅”意味着什么。 : - )
2 Git使用名称apply
来记住当前的存储,而(ab)使用drop
的reflog来维护“存储堆栈”的剩余部分。内部的分支名称都具有git stash apply
形式,因此refs/stash
不是分支名称。
3 如果您使用refs/stash
,它运行的不只是refs/heads/name
:它将保存的索引状态提取到工作树。这里的目标是让工作树的设置与索引的设置方式相同,这样您就可以测试您要提交的内容。如脚注1所示,这里有一个很小但相当讨厌的错误,其中包含refs/stash
的许多版本,如果正确的工作树版本,则隐藏的工作树状态意外地采用索引版本而不是工作树版本匹配git stash --keep-index
版本。
答案 2 :(得分:1)
你可以反向修补存储(已经提到的应该仍然存在,因为git不会丢弃存储,如果它不能干净地应用)
git stash show -p stash@{0} | git apply -R
答案 3 :(得分:0)
所以,在所有情况下,我都不是100%肯定答案。在我的情况下,当我输入git stash pop
并且我在分支bar
时,存在冲突。因此,虽然它应用了藏匿处,但它没有放下藏匿物。因此,要撤消并正确将存储应用于分支foo
,它只是
git reset --hard # resets bar to before the stash pop
git checkout -b foo
git stash pop
如果与分支bar
没有冲突,则只是
git stash # restash
git checkout -b foo
git stash pop