Subject: Re: unwanted interaction of git stash and cherry-pick --abort

From: Junio C Hamano <[email-masked]>
Date: Sun, 20 Apr 2025 14:05:37 -0700

Markus Raab <[email-masked]> writes:

> Dear Brian,
>
> Thanks for the quick reply.
>
> Unfortunately, I forgot an essential line in my first e-mail, thus
> I've resent my e-mail shortly later again.
>
> To "fix" your shell script (make the files get lost), git stash pop
> should be inserted before the last line:
>
> ----
> #!/bin/sh
>
> git init-db --object-format=sha256
> git commit --allow-empty -m +
> oid=$(git rev-parse HEAD)
> echo a > a
> echo b > b
> git add a b # some arbitrary files with content
> git stash
> git cherry-pick $oid
> git stash pop
> git cherry-pick --abort
> ----

So, this is not limited to stash at all.

When you start "cherry-pick", which cannot complete without your
help (most often, this happens when the cherry-picked change
conflicts with what you have in the current commit), the command
stops and gives control back.

At that point, it is up to you to do anything to bring your index
into a shape that you desire the "cherry-picked" commit to have.
You'd do so by editing working tree files (often with conflicts),
creating new files, removing unneeded files, etc., and then updating
your index with these changes, and then "cherry-pick --continue" to
conclude.

Or, after mucking your working tree and index to "correct" the
stalled "cherry-pick", you may decide that it is not a good idea to
cherry-pick the commit after all.  You say "cherry-pick --abort" and
you expect your index to be clean relative to HEAD, and working tree
files also adjusted for it.  You may have edited existing working
tree files, created new files, or removed files that you thought
unneeded, before deciding that it is not a good idea to perform this
cherry-pick.  And the way to ask Git to revert all of these changes
you made to your index and your working tree file, and get you out
of the "cherry-picking" state, is to run "cherry-pick --abort".

Instead of doing "git stash pop" there, you could have added
arbitrary files with content, or edited working tree files, or
any other changes manually, and "cherry-pick --abort" would have
removed such changes to your index and your working tree files, just
the same way.

So there is nothing unexpected.

There is another aspect in this story.

"git stash pop" will remove the stash entry after updating your
index and your working tree files, and unless you save them away
elsewhere, if you make further changes to these files, there is no
easy way to get that exact change you took out of the stash entry
back.

And this is not limited to "cherry-pick --abort".

You can edit these files manually (totally outside of Git), remove
them, or ask Git to give you a clean slate with "git reset --hard".

So one lesson we can learn from this episode is

    Never use "git stash pop" WHEN IT IS POSSIBLE YOU MAY LATER
    CHANGE YOUR MIND.  "pop" applies and then drops the stash entry,
    so what you will have in your index and working tree will become
    the ONLY copy of the change you previously stashed.

If you are in doubt, use "git stash apply" instead.  The stash entry
will stay, so when you decide to get rid of the change you pulled
out of the stash entry into the working tree, you can safely do so
with "reset --hard" and nothing is lost.

Of course, you need to remember at some point to drop the entry you
no longer need with "git stash drop" if you take that approach.

HTH.