中止 Git 中的 stash pop
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8515729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Aborting a stash pop in Git
提问by Casebash
I popped a stash and there was a merge conflict. Unlike the question that is listed as a duplicate, I already had some uncommitted changes in the directory which I wanted to keep. I don't just want to make the merge conflict disappear, but also to get my directory back to the state it was before the pop.
我弹出了一个藏匿处,发生了合并冲突。与列为重复的问题不同,我已经在想要保留的目录中进行了一些未提交的更改。我不仅想让合并冲突消失,还要让我的目录恢复到弹出之前的状态。
I tried git merge --abort
, but git claimed no merge was in progress. Is there an easy way to abort a pop without destroying the changes I originally had in the directory?
我试过git merge --abort
,但 git 声称没有合并正在进行。有没有一种简单的方法可以在不破坏我最初在目录中所做的更改的情况下中止弹出窗口?
采纳答案by Ben Hymanson
Ok, I think I have worked out "git stash unapply". It's more complex than git apply --reverse
because you need reverse merging action in case there was any merging done by the git stash apply
.
好的,我想我已经解决了“git stash unapply”。它比git apply --reverse
因为您需要反向合并操作更复杂,以防万一git stash apply
.
The reverse merge requires that all current changes be pushed into the index:
反向合并要求将所有当前更改推送到索引中:
git add -u
git add -u
Then invert the merge-recursive
that was done by git stash apply
:
然后反转merge-recursive
由git stash apply
:
git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Now you will be left with just the non-stash changes. They will be in the index. You can use git reset
to unstage your changes if you like.
现在,您将只剩下非存储更改。他们将在索引中。git reset
如果您愿意,可以使用取消暂存您的更改。
Given that your original git stash apply
failed I assume the reverse might also fail since some of the things it wants to undo did not get done.
鉴于您的原始git stash apply
失败,我认为反过来也可能失败,因为它想要撤消的一些事情没有完成。
Here's an example showing how the working copy (via git status
) ends up clean again:
这是一个示例,显示了工作副本(via git status
)如何再次清理干净:
$ git status
# On branch trunk
nothing to commit (working directory clean)
$ git stash apply
Auto-merging foo.c
# On branch trunk
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: foo.c
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git add -u
$ git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1
Auto-merging foo.c
$ git status
# On branch trunk
nothing to commit (working directory clean)
回答by jmoz
My use case: just tried popping onto the wrong branch and got conflicts. All I need is to undo the pop but keep it in the stash list so I can pop it out on the correct branch. I did this:
我的用例:只是尝试弹出错误的分支并发生冲突。我所需要的只是撤消弹出,但将其保留在存储列表中,以便我可以将其弹出到正确的分支上。我这样做了:
git reset HEAD --hard
git checkout my_correct_branch
git stash pop
Easy.
简单。
回答by DavidG
Edit: From the git help stash
documentation in the pop section:
编辑:从git help stash
弹出部分的文档中:
Applying the state can fail with conflicts; in this case, it is not removed from the stash list. You need to resolve the conflicts by hand and call git stash drop manually afterwards.
应用状态可能会因冲突而失败;在这种情况下,它不会从存储列表中删除。您需要手动解决冲突,然后手动调用 git stash drop。
If the --index option is used, then tries to reinstate not only the working tree's changes, but also the index's ones. However, this can fail, when you have conflicts (which are stored in the index, where you therefore can no longer apply the changes as they were originally).
如果使用 --index 选项,则不仅尝试恢复工作树的更改,还尝试恢复索引的更改。但是,当您遇到冲突(存储在索引中,因此您无法再像原来那样应用更改时),这可能会失败。
Try hardcopying all your repo into a new dir (so you have a copy of it) and run:
尝试将所有 repo 硬拷贝到一个新目录中(这样你就有了它的副本)并运行:
git stash show
and save that output somewhere if you care about it.
git stash show
如果您关心它,并将该输出保存在某个地方。
then: git stash drop
to drop the conflicting stash
then: git reset HEAD
然后:git stash drop
删除冲突的存储然后:git reset HEAD
That should leave your repo in the state it was before (hopefully, I still haven't been able to repro your problem)
这应该使您的回购处于之前的状态(希望我仍然无法重现您的问题)
===
===
I am trying to repro your problem but all I get when usin git stash pop
is:
我正在尝试重现您的问题,但在使用时我得到的git stash pop
只是:
error: Your local changes to the following files would be overwritten by merge:
...
Please, commit your changes or stash them before you can merge.
Aborting
In a clean dir:
在干净的目录中:
git init
echo hello world > a
git add a & git commit -m "a"
echo hallo welt >> a
echo hello world > b
git add b & git commit -m "b"
echo hallo welt >> b
git stash
echo hola mundo >> a
git stash pop
I don't see git trying to merge my changes, it just fails. Do you have any repro steps we can follow to help you out?
我没有看到 git 试图合并我的更改,它只是失败了。您是否有任何我们可以遵循的重现步骤来帮助您?
回答by Kenn Sebesta
I have always used
我一直用
git reset --merge
git reset --merge
I can't remember it ever failing.
我不记得它曾经失败过。
回答by hugo der hungrige
If you don't have to worry about any other changes you made and you just want to go back to the last commit, then you can do:
如果您不必担心所做的任何其他更改并且只想回到上次提交,那么您可以执行以下操作:
git reset .
git checkout .
git clean -f
回答by agentgonzo
OK, I think I have managed to find a work-flow that will get you back to where you need to be (as if you had not done the pop).
好的,我想我已经设法找到了一个工作流程,可以让你回到你需要的地方(就像你没有完成流行一样)。
TAKE A BACKUP BEFOREHAND!! I don't know whether this will work for you, so copy your whole repo just in case it doesn't work.
事先备份!!我不知道这是否适合你,所以复制你的整个 repo 以防万一它不起作用。
1) Fix the merge problems and fix all the conflict by selecting all the changes that come from the patch (in tortoisemerge, this shows up as one.REMOETE (theirs)).
1)通过选择来自补丁的所有更改来修复合并问题并修复所有冲突(在tortoisemerge中,这显示为one.REMOETE(他们的))。
git mergetool
2) Commit these changes (they will already be added via the mergetool command). Give it a commit message of "merge" or something you remember.
2) 提交这些更改(它们已经通过 mergetool 命令添加)。给它一个“合并”或你记得的东西的提交信息。
git commit -m "merge"
3) Now you will still have your local unstaged changes that you started originally, with a new commit from the patch (we can get rid of this later). Now commit your unstaged changes
3) 现在,您仍然拥有最初开始的本地未暂存更改,以及补丁中的新提交(我们稍后可以删除它)。现在提交未暂存的更改
git add .
git add -u .
git commit -m "local changes"
4) Reverse the patch. This can be done with the following command:
4) 反转补丁。这可以通过以下命令完成:
git stash show -p | git apply -R
5) Commit these changes:
5) 提交这些更改:
git commit -a -m "reversed patch"
6) Get rid of the patch/unpatch commits
6)摆脱补丁/取消补丁提交
git rebase -i HEAD^^^
from this, remove the two lines with 'merge' and 'reversed patch' in it.
从此,删除其中包含“合并”和“反向补丁”的两行。
7) Get your unstanged changes back and undo the 'local changes' commit
7) 取回您的无意义更改并撤消“本地更改”提交
git reset HEAD^
I've run through it with a simple example and it gets you back to where you want to be - directly before the stash was popped, with your local changes and with the stash still being available to pop.
我已经用一个简单的例子完成了它,它让你回到你想要的地方 - 直接在存储被弹出之前,你的本地更改和存储仍然可以弹出。
回答by pid
I solved this in a somewhat different way. Here's what happened.
我以稍微不同的方式解决了这个问题。这就是发生的事情。
First, I popped on the wrong branch and got conflicts. The stash remained intact but the index was in conflict resolution, blocking many commands.
首先,我弹出错误的分支并发生冲突。存储保持完整,但索引处于冲突解决状态,阻止了许多命令。
A simple git reset HEAD
aborted the conflict resolution and left the uncommitted (and UNWANTED) changes.
一个简单的git reset HEAD
中止冲突解决并留下未提交的(和不需要的)更改。
Several git co <filename>
reverted the index to the initial state. Finally, I switched branch with git co <branch-name>
and run a new git stash pop
, which resolved without conflicts.
有几个git co <filename>
将索引恢复到初始状态。最后,我切换了分支git co <branch-name>
并运行了一个 new git stash pop
,它在没有冲突的情况下解决了。
回答by asmeurer
Some ideas:
一些想法:
Use
git mergetool
to split the merge files into original and new parts. Hopefully one of those is the file with your non-stash changes in it.Apply the diff of the stash in reverse, to undo just those changes. You'll probably have to manually split out the files with the merge conflicts (which hopefully the above trick will work for).
使用
git mergetool
到合并文件分割成原始的和新的部件。希望其中之一是包含非存储更改的文件。反向应用存储的差异,以撤消那些更改。您可能必须手动拆分具有合并冲突的文件(希望上述技巧适用)。
I didn't test either of these, so I don't know for sure of they will work.
我没有测试其中任何一个,所以我不确定它们是否会起作用。
回答by Jakub Nar?bski
I could reproduce clean git stash pop
on "dirty" directory, with uncommitted changes, but not yet pop that generates a merge conflict.
我可以git stash pop
在“脏”目录上重现干净,未提交的更改,但尚未弹出会产生合并冲突。
Ifon merge conflict the stash you tried to apply didn't disappear, you can try to examine git show stash@{0}
(optionally with --ours
or --theirs
) and compare with git statis
and git diff HEAD
. You should be able to see which changes came from applying a stash.
如果在合并冲突时,您尝试应用的存储没有消失,您可以尝试检查git show stash@{0}
(可选用--ours
或--theirs
)并与git statis
和进行比较git diff HEAD
。您应该能够看到哪些更改来自应用存储。
回答by robrich
If DavidG is correct that it didn't pop the stash because of the merge conflict, then you merely need to clean up your working directory. Quickly git commit
everything you care about. (You can reset
or squash
the commit later if you're not done.) Then with everything you care about safe, git reset
everything else that git stash pop
dumped into your working directory.
如果 DavidG 没有因为合并冲突而弹出存储是正确的,那么您只需要清理您的工作目录。快速处理git commit
你关心的一切。(如果你没有完成,你可以reset
或者squash
稍后提交。)然后你关心的git reset
一切都是安全的,其他一切都git stash pop
转储到你的工作目录中。