It seems like the tricky part of this question revolves around what you want the stash to look like when you're done. Since git stash {pop|apply}
only affects the working tree (and sometimes index), it's easy enough to selectively take changes from a stash (enough so that I initially thought you were over-thinking the problem):
git stash pop
# maybe a 'git reset head' if the index was changed
git checkout -- file.with.unwanted.changes.in.stash
But those commands remove the stash entirely; and by contrast if I'd said git stash apply
instead of pop
, that leaves the stash unchanged. It sounds like you want the stash to remain with the changes you've selected (in case you should need to apply them again).
(I suppose alternately there could be times you'd want exactly the opposite - to leave in the stash those changes that you didn't apply, so they can be applied later.)
So taking a step back: what is involved in modifying a stash?
A stash, really, comprises two or three temporary commits. The special ref stash
points to these commits, and a "stack" of multiple stashes is maintained using the reflog (which may be a bit of a hack, but generally is effective).
So to modify the stash is to create new commits (because commits are immutable) and rearrange the stash
ref and reflog accordingly.
This is why the notations LeGEC mentions will work and may give you extra flexibility in reading a stash. But because the reflog usage is not the same as for non-stash refs, leveraging this fact to contrive a way to write to a stash could have unexpected results. I'm not saying the results would be horrible, or impossible to predict/control; but I think in the end you'd create more complexity than you'd avoid.
So if we confine ourselves to actual documented git-stash
subcommands, then a stash is more or less atomic. When you create a stash there's a patch
mode that lets you select working changes to put in the stack, but I'm aware of no corresponding functionality for pop/apply. Still, that's something:
If you have a clean work tree and a stash you want to split, you could try things like:
Apply some changes, and keep those same changes in the stash
git stash pop
git stash -p
# select the "good" changes
git checkout -- .
git stash apply
Apply some changes, and keep the remaining changes in the stash
git stash pop
git stash -p
# select the "unwanted" changes
Split the stash into two parts, decide what to do with them later
git stash pop
git stash -p
# select the "good" changes
git stash
# now the "good" changes are stash@{1} and the "unwanted" are stash@{0}