I have a serie of files into a stash (stash{0}
) and I would like to git apply
just some parts/hunks of these files (usually known as Interactive mode).
Is it possible?
I've seen that is possible to perform a
git stash save -p 'Stash name'
but it seems not possible to do
git stash apply -p 'Stash name'
Do you know a way to achieve it?
To retrieve changes out of the stash and apply them to the current branch you're on, you have two options: git stash apply STASH-NAME applies the changes and leaves a copy in the stash. git stash pop STASH-NAME applies the changes and removes the files from the stash.
git stash apply vs pop : They are almost similar except the fact that git stash pop throws away the (topmost, by default) stash when applying it, whereas git stash apply leaves it within the stash list for possible later use (or you'll then git stash drop it).
If you made two stashes, then just call git stash pop twice. As opposed to git stash apply , pop applies and removes the latest stash. You can also reference a specific stash, e.g.
Is it possible?
git checkout -p stash@{0}
Where you can replace the 0
in stash@{0}
with the index of the stash you want to apply.
Use git stash list
and git show -p stash@{n}
if unsure which n
is the stash you want to apply.
Don't forget to git stash drop stash@{n}
when you know you won't need that stash anymore, since git checkout
obviously will not drop the stash for you.
The key is to realize that stashes are, in essence, references to commits just like tags and branches.
Indeed, they're stored in .git/refs/stash
, one line per stash hash.
As @mgadda mentioned in the comments below, git checkout -p
tries to apply the whole difference between a commit and the current workspace.
In the case of a git stash, if the stash you're trying to apply was done against a different commit, then git checkout -p stash@{n}
will try to apply interactively all the differences between the commit stash@{n}
and the commit of the current workspace, including all their parent commits that are different.
For example, if you're trying to apply a stash that was saved "many commits ago" into the current workspace, git checkout -p stash@{n}
will try to apply not only the changes in the stash proper, but will also try to revert all changes that happened between the commit on which the stash is based and the current commit.
Conversely, if you're trying to apply a stash "from the future", i.e. into a branch that is a number of commits from before the commit on which the stash is based, then git checkout -p stash@{n}
will try to also apply all the other changes that happened between the current commit and the commit from the future, besides the changes from the stash itself.
(In case you're wondering, git checkout -p stash@{n}
a stash from a parallel branch will try to revert all changes between the current commit and the original branching point and also apply all changes between the branching point and the other branch, besides the change in the stash).
There are a few workarounds, none of them are perfect for every situation:
git checkout -p stash@{n}
git stash pop
, then git stash
again before doing git checkout -p ...
. But if you wanted to do a partial apply of your stash to avoid conflicts, this won't really help. In that case, see solution 4 below.git difftool
and "apply left" only the changes you're interested in:git difftool -d stash@{n}
to compare a whole stash and all its files
git difftool stash@{n} -- path/to/file
to compare a single file
Step by step:
git checkout stash@{n}^ # notice the "^". # Now you're in a detached head in the parent commit of the stash. # It can be applied cleanly: git stash apply stash@{n} # Now save only the diffs you're interested in: git stash -p # remove the rest of the old stash git checkout -- . # be careful or you could remove unrelated changes # go back to the branch where you want to apply the smaller stash git checkout <my previous branch> # apply the smaller stash git stash pop
What I often do (in git bash) is
git stash show -p 'stash@{0}' >tmp.patch
Then I edit the file and remove the parts I don't want. Finally I say
<tmp.patch git apply
or
<tmp.patch patch -p1
It doesn't work for binary files, though, but neither does the accepted answer (using checkout -p) for them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With