Git stash: "Cannot apply to a dirty working tree, please stage your changes"
Solution 1
When I have to apply stashed changes to a dirty working copy, e.g. pop more than one changeset from the stash, I use the following:
$ git stash show -p | git apply -3 && git stash drop
Basically it
- creates a patch
- pipes that to the apply command
- if there are any conflicts they will need to be resolved via 3-way merge
- if apply (or merge) succeeded it drops the just applied stash item...
I wonder why there is no -f
(force) option for git stash pop
which should exactly behave like the one-liner above.
In the meantime you might want to add this one-liner as a git alias:
$ git config --global --replace-all alias.unstash \
'!git stash show -p | git apply -3 && git stash drop'
$ git unstash
Thanks to @SamHasler for pointing out the -3
parameter which allows to resolve conflicts directly via 3-way merge.
Solution 2
I do it in this way:
git add -A
git stash apply
and then (optionaly):
git reset
Solution 3
You can do this without having to stash your current changes by exporting the stash you want as a patch file and manually applying it.
For example, say you want to apply stash@{0}
to a dirty tree:
Export
stash@{0}
as a patch:git stash show -p stash@{0} > Stash0.patch
Manually apply the changes:
git apply Stash0.patch
If the second step fails, you will have to edit the Stash0.patch
file to fix any errors and then try git apply
again.
Solution 4
Either clean your working directory with git reset, commit the changes, or, if you want to stash the current changes, try:
$ git stash save "description of current changes" $ git stash pop stash@{1}
This will stash the current changes, and then pop the second stash from the stash stack.
Solution 5
Mathias's solution is definitely the closest to a git stash pop --force
(and really, c'mon Git devs, let's get this option already!)
However, if you want to do the same thing using only Git commands, you can:
git commit -a -m "Fixme"
git stash pop
git commit -a --amend
git reset HEAD~
In other words, make a commit (which we will never push) of your current changes. Now that your workspace is clean, pop your stash. Now, commit the stash changes as an amendment to your previous commit. Having done that you now have both sets of changes combined in a single commit ("Fixme"); just git reset
(--soft
NOT --hard
so nothing is actually lost) your checkout to "one before that commit", and now you have both sets of changes, completely uncommitted.
EDIT
I just realized it's actually even easier; you can completely skip step 3, so ...
git commit -a -m "Fixme"
git stash pop
git reset HEAD~
(Commit current changes, pop off the stashed changes, reset that first commit to get both sets of changes combined in an uncommitted state.)
avernet
Co-founder of Orbeon, developing Orbeon Forms: web forms, open source, for the enterprise. Passionate about technology, and how it improves the world.
Updated on July 08, 2022Comments
-
avernet almost 2 years
I am trying to apply changes I stashed earlier with
git stash pop
and get the message:Cannot apply to a dirty working tree, please stage your changes
Any suggestion on how to deal with that?
-
manneym almost 14 yearsThis is practical and workable for the case that, I made refactoring on a dir (removed it, and created a symlink with its name). Git couldn't tell what were my working copy changes.
-
Shiki over 13 yearsThis worked great. I wasn't able to apply a stash even though I'm pretty sure my working tree is clean.
-
manneym over 13 yearsThanks a lot Yar. I was frustrated by how Git strangely behaved on my local repo just now, the same problem you described.
-
Factor Mystic about 13 yearsIs
git stash show -p | git apply
different thangit stash apply
? -
muhqu about 13 yearsJo Factor,
git stash apply
will not apply the stashed changes if you have a dirty working copy. So you can seegit stash show -p | git apply
as some sort of forced stash apply. -
Elazar Leibovich about 13 yearsBut this guy want the two stashes applied!
-
William Pursell about 13 years@Elazar You are reading into the question. The OP merely wants to apply a previous stash. If you are correct that the current changes are to be kept, the solution can be repeated: pop, commit, repeat.
-
Elazar Leibovich about 13 yearsI think he want both of them uncommited. But then again, he can commit them twice and squash them into a single commit.
-
sscirrus about 12 years@MikeCooper - I think he just meant add whatever you want to add before committing.
-
Roger Alien about 12 yearsdoesn't help But help: git reset HEAD and unstash changes after that.
-
Dorian about 12 yearsYes, I had to remove lines about a binary file.
-
Joakim almost 12 yearsThis command launched vimdiff for me, which gave me the error "Vim: Warning: Output is not a terminal". This might be because I'm using a diff wrapper script like this: technotales.wordpress.com/2009/05/17/git-diff-with-vimdiff
-
Snowcrash over 11 years@Joakim Yes, you just need to comment out the diff wrapper in .gitconfig and you're good. Remember to uncomment it after applying your changes if you want to continue using vimdiff.
-
peterflynn about 11 years+1! This is simpler than the other solutions that involve generating patches or amending commits, and it keeps your local changes safely isolated from the applied stash changes until you're sure the changes were merged properly.
-
Kirby over 10 yearsI've been using this solution for awhile. Generally it works, but sometimes there can be icky issues applying patches, especially if the patch or underlying code base has changed a lot since the patch was created. Now that I'm more familiar with git, I see the beauty of sergey_mo's "git add, git stash, git reset" solution below
-
Aleksandr Dubinsky almost 10 yearsI get "error: patch failed...patch does not apply" for one of the files. I wish it gave a merge conflict.
-
Aleksandr Dubinsky almost 10 yearsI get error "... already exists, no checkout...Could not restore untracked files from stash"
-
Aleksandr Dubinsky almost 10 yearsI get error "... already exists, no checkout...Could not restore untracked files from stash"
-
Smilediver almost 10 years@AleksandrDubinsky I got around that by doing
git stash show -p | git apply -3
which falls back to 3 way merge. Another option would be to use--reject
which leaves rejected hunks in *.rej files. -
muhqu over 9 years@SamHasler awesome! thanks for pointing that out. I did not yet knew about the
-3
option ofgit apply
. thanks. -
Brad Cupit over 8 yearsI used
git add -u
, which is like-A
except it doesn't add untracked files. -
Jonathan. almost 8 yearsWow git is stupid here. I'm trying to pop a stash that has modified file that isn't modified currently, you'd think it would just work..
-
Iulian Onofrei about 7 yearsWhy would you want to drop a stash when applying it?!
-
silvenon over 6 yearsThis solution didn't work for me, it failed with
error: <file> does not match index
for every modified file. However, another solution worked.