Git stash: "Cannot apply to a dirty working tree, please stage your changes"

53,832

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

  1. creates a patch
  2. pipes that to the apply command
  3. if there are any conflicts they will need to be resolved via 3-way merge
  4. 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:

  1. Export stash@{0} as a patch:

    git stash show -p stash@{0} > Stash0.patch
    
  2. 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:

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git commit -a --amend
  4. 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 ...

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. 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.)

Share:
53,832
avernet
Author by

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, 2022

Comments

  • avernet
    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
    manneym almost 14 years
    This 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
    Shiki over 13 years
    This worked great. I wasn't able to apply a stash even though I'm pretty sure my working tree is clean.
  • manneym
    manneym over 13 years
    Thanks a lot Yar. I was frustrated by how Git strangely behaved on my local repo just now, the same problem you described.
  • Factor Mystic
    Factor Mystic about 13 years
    Is git stash show -p | git apply different than git stash apply?
  • muhqu
    muhqu about 13 years
    Jo Factor, git stash apply will not apply the stashed changes if you have a dirty working copy. So you can see git stash show -p | git apply as some sort of forced stash apply.
  • Elazar Leibovich
    Elazar Leibovich about 13 years
    But this guy want the two stashes applied!
  • William Pursell
    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
    Elazar Leibovich about 13 years
    I think he want both of them uncommited. But then again, he can commit them twice and squash them into a single commit.
  • sscirrus
    sscirrus about 12 years
    @MikeCooper - I think he just meant add whatever you want to add before committing.
  • Roger Alien
    Roger Alien about 12 years
    doesn't help But help: git reset HEAD and unstash changes after that.
  • Dorian
    Dorian about 12 years
    Yes, I had to remove lines about a binary file.
  • Joakim
    Joakim almost 12 years
    This 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
    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
    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
    Kirby over 10 years
    I'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
    Aleksandr Dubinsky almost 10 years
    I get "error: patch failed...patch does not apply" for one of the files. I wish it gave a merge conflict.
  • Aleksandr Dubinsky
    Aleksandr Dubinsky almost 10 years
    I get error "... already exists, no checkout...Could not restore untracked files from stash"
  • Aleksandr Dubinsky
    Aleksandr Dubinsky almost 10 years
    I get error "... already exists, no checkout...Could not restore untracked files from stash"
  • Smilediver
    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
    muhqu over 9 years
    @SamHasler awesome! thanks for pointing that out. I did not yet knew about the -3 option of git apply. thanks.
  • Brad Cupit
    Brad Cupit over 8 years
    I used git add -u, which is like -A except it doesn't add untracked files.
  • Jonathan.
    Jonathan. almost 8 years
    Wow 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
    Iulian Onofrei about 7 years
    Why would you want to drop a stash when applying it?!
  • silvenon
    silvenon over 6 years
    This solution didn't work for me, it failed with error: <file> does not match index for every modified file. However, another solution worked.