Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to undo git stash apply

Tags:

git

I have not commited changes in my branch. I decided to apply some of my stash. Stash applied with Auto-merging and conflicts. I realize, that stashed changes are not appropriate for me and want to unstash changes, but not loose my changes before stash. Tried to do

git stash show -p | git apply -R

but it is not work for me. I have error with message: error: patch failed, ...error: patch does not apply

How to undo stash apply and not loose my not committed changes?

like image 862
Nikolas Avatar asked Nov 28 '18 14:11

Nikolas


People also ask

Is there a way to revert git stash?

To undo a git stash , use the git stash pop command. It will re-apply your stash to your working copy.

Can you git stash apply twice?

You can reapply stashed changes with the commands git stash apply and git stash pop . Both commands reapply the changes stashed in the latest stash (that is, stash@{0} ).


1 Answers

The problem with reverse-applying the stash is due to the merge conflicts. I'll go into more detail about that at the end if you want to dig into that, but more importantly: what to do instead?

Generally git stash apply is a fairly safe command. It requires that the work tree match the index, and it is only expected to write to the work tree, so it would seem easy to undo.

It can be a bit of a pain when there are conflicts, though, because now it updates the index for conflict resolution. So now there are (at least) five possible states for each file:

1) Neither your local changes nor the stash applied changes to the file. Nothing to see here.

2) You applied local changes to the file, and the stash did not apply changes to the file. Your locally-changed version is in the index, and you can leave this file alone.

3) You had not applied local changes to the file, and the stash did apply changes to it. The index contains the file as modified by the stash. This looks pretty much like case 2, so knowing the difference is the first challenge (see below); once you identify a file in this state, you could revert this file to the previously-committed version (but might not want to just yet; again, see below)

git checkout HEAD -- file/with/only/stashed/changes

4) You had applied local changes to the file, and the stash applied conflicting changes to the same file. In this case, the conflict-marked version of the file is in the work tree. You can restore your version by saying

git checkout --ours -- file/with/conflicting/changes

5) You had applied local changes to the file, and the stash applied changes to the same file, but the changes are not in conflict (i.e. automatic merge resolution combined the changes successfully). This is the biggest problem case. It again looks pretty much like cases 2 and 3, and to fix it you need to separate your changes from those added by the stash.

Ok, so cases 1 and 2 take no action, and 4 is easy to find and resolve. The problems are 3 and 5. There are two ways to go about fixing this:

Building on what you were trying to do before, you could store the patch from the stash and remove the entries for files that were conflicted. Then you would resolve the conflicts with checkout --ours, and reverse-apply the rest of the patch.

Of you could handle it file by file, using

git stash show --name-only

to see if the stash modified a file, and something like

git diff stash -- path/to/file

to see if the file contains local modifications. You'd still have to do something like reverse-patching for files that were modified in both places without conflict.

Why the patch doesn't work

The stash can't be reverse-applied as a patch because of the conflict markers. For example, maybe you started with a file

this
is
content

and the stash wants to change it to

here
is
content

but you had locally changed it to

this
file contains
content

so the stash apply got a conflict. Well, now the working copy says

<<<<<<< Updated upstream
this
file contains
=======
here
is
>>>>>>> stashed changes
content

The reverse patch from the stash would change line 1 from here to this, but it doesn't find here at line 1

like image 175
Mark Adelsberger Avatar answered Sep 28 '22 07:09

Mark Adelsberger