554

I stashed my changes. Now I want to unstash only some files from the stash. How can I do this?

alex
  • 479,566
  • 201
  • 878
  • 984
morpheus
  • 18,676
  • 24
  • 96
  • 159
  • 5
    I think you have to apply the whole stash, but then you can selectively re-stash. – Richard Mar 07 '13 at 06:30
  • Just in your future development, try to avoid stashing files commit them instead, because git stash is not recommended – Abdou Tahiri Mar 14 '16 at 18:41
  • 5
    @AbdouTahiri What is wrong with the stash? – alex Mar 17 '16 at 09:16
  • @alex With "git stash", you can have multiple different stashed things too, but they don't queue up on each other - they are just random independent patches that you've stashed away because they were inconvenient at some point. – Abdou Tahiri Mar 17 '16 at 09:39
  • 52
    @AbdouTahiri Uhhhh.. git stash is a legit feature, and extremely useful. I use it daily. Say, a coworker needs me to review something but I'm in the middle of a complex change set. I'm not going to commit a pile of broken code just so I can switch branches. I'm going to stash, switch branches, review, switch back, unstash. Do you care to elaborate on *who* or *why* git stash is supposedly "not recommended"? Just because *your* git stash history is muddied up and hard to read doesn't mean everyone elses is. A messy git stash set is just bad workflow, not a flaw of Git. – dudewad May 11 '16 at 01:25
  • 10
    @alex Nothing. Nothing is wrong with git stash. Keep using it. – dudewad May 11 '16 at 01:26
  • I thought it might be possible to patch an already changed file using `git show stash@{0} -- | git apply --check` but it keeps saying `fatal: unrecognized input` – joeytwiddle May 23 '16 at 03:27
  • 5
    Possible duplicate of [How would I extract a single file (or changes to a file) from a git stash?](http://stackoverflow.com/questions/1105253/how-would-i-extract-a-single-file-or-changes-to-a-file-from-a-git-stash) – Jeff Puckett Sep 07 '16 at 01:56
  • this is trivial in [emacs magit mode](https://magit.vc/), sorry command line people. It is literally 3 key presses – A_P Feb 23 '23 at 15:47
  • dudewad, i would be much better to never have a "pile of broken code," and what's more, never branch. – NickDanger66 May 22 '23 at 19:03

10 Answers10

664

As mentioned below, and detailed in "How would I extract a single file (or changes to a file) from a git stash?", you can apply use git checkout or git show to restore a specific file.

git checkout stash@{0} -- <filename>

With Git 2.23+ (August 2019), use git restore, which replaces the confusing git checkout command:

git restore --source=stash@{0} -- <filename>

That does overwrite filename: make sure you didn't have local modifications, or you might want to merge the stashed file instead.

(As commented by Jaime M., for certain shell like tcsh where you need to escape the special characters, the syntax would be: git checkout 'stash@{0}' -- <filename>)

or to save it under another filename:

git show stash@{0}:<full filename>  >  <newfile>

(note that here <full filename> is full pathname of a file relative to top directory of a project (think: relative to stash@{0})).

yucer suggests in the comments:

If you want to select manually which changes you want to apply from that file:

git difftool stash@{0}..HEAD -- <filename>

Vivek adds in the comments:

Looks like "git checkout stash@{0} -- <filename>" restores the version of the file as of the time when the stash was performed -- it does NOT apply (just) the stashed changes for that file.
To do the latter:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(as commented by peterflynn, you might need | git apply -p1 in some cases, removing one (p1) leading slash from traditional diff paths)


As commented: "unstash" (git stash pop), then:

  • add what you want to keep to the index (git add)
  • stash the rest: git stash --keep-index

The last point is what allows you to keep some file while stashing others.
It is illustrated in "How to stash only one file out of multiple files that have changed".

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 5
    This doesn't work if you can't `git stash pop` due to file conflicts. Balamurugan A's answer did the trick for me in that case. – Andrey Dec 22 '14 at 15:02
  • 1
    Of if you want to select manually which changes you want to apply from that file you can use git difftool stash@{0}..HEAD -- – yucer Jun 29 '16 at 10:19
  • @yucer Nice. I have included your comment in the answer for more visibility. – VonC Jun 29 '16 at 10:42
  • 6
    Looks like "git checkout stash@{0} -- " restores the version of the file as of the time when the stash was performed -- it does NOT apply (just) the stashed changes for that file. To do the latter: "git diff stash@{0}^1 stash@{0} -- | git apply" – Vivek Oct 13 '16 at 07:17
  • I ran into a case where the `| git apply` trick (to merge the stashed copy with the local copy) failed with the error "patch does not apply." But using `| patch -p1` instead, the merge worked perfectly! – peterflynn Jan 04 '17 at 01:11
  • @peterflynn Thank you. I have included your comment in the answer for more visibility. – VonC Jan 04 '17 at 05:19
  • Note that you have to _escape_ the special characters in some shells like tcsh, so the command will be `git checkout 'stash@{0}' -- ` – Jaime M. Sep 04 '17 at 16:16
  • 1
    @JaimeM. Thank you. I have included your comment in the answer for more visibility. – VonC Sep 04 '17 at 17:03
  • 1
    Assuming that `unstash` means `pop`, as it seems to me that it probably would in most cases, this only partially answers the question. How do you then remove the selectively applied pieces from the stash in order to avoid later conflicts and/or confusion when popping the remaining changes? – DylanYoung Oct 16 '17 at 21:01
  • @DylanYoung Not sure: do you have a specific case in mind? Otherwise, pop + add + stash --keep-index (mentioned at the end of this answer) seems pretty straightforward. – VonC Oct 16 '17 at 21:27
  • If you have existing changes that you're merging with select bits from the stash, then updating to make it all fit together, it can get messy. Of course, a temporary commit and then squashing it together with the stashed changes would work, but it requires knowing what you're doing *very* well. Whereas a command like `stash pop --interactive`, while technically complex to implement, is much less finicky for the user. – DylanYoung Oct 17 '17 at 15:36
  • You're of course correct though, that the guts of such a command would almost certainly involve something like what you've outlined, similarly to the way `stash -u` just creates some support commits to work. Just curious if there is a supported solution (or if it's on the timeline) and pointing out that, the given solutions are not super clean and or require a lot of overhead on the part of the user to make sure relevant changes stay where they're supposed to and don't get all mixed up.. – DylanYoung Oct 17 '17 at 15:39
  • 1
    @DylanYoung OK. I am not aware of such a solution right now. – VonC Oct 17 '17 at 15:44
  • Why do I get `$ git checkout stash@{0} --filename ./myFile.java error: unknown option `filename' ` – Janac Meena Jan 15 '19 at 16:18
  • 1
    @JanacMeena because there should be a space between the '`--`' and the filename (as there is in the answer above). See https://stackoverflow.com/a/1192194/6309 for more on the '`--`' notation. – VonC Jan 15 '19 at 16:22
  • @VonC thanks! Also, how do I pop a specific file from my stash, (rather than just apply it) if this file doesn't currently exist in my working directory - it only exists in the stash? – Janac Meena Jan 15 '19 at 16:26
  • 1
    @JanacMeena The `git show stash@{0}: > ` command should be able to create that file in the working tree, even if it existed *only* in the stash. – VonC Jan 15 '19 at 16:54
  • @VonCgit checkout stash@{0} -- will replace with stash changes. – Akhil Surapuram Apr 11 '19 at 04:15
  • @AkhilSurapuram Exactly. That is the idea. https://stackoverflow.com/a/50370632/6309 would merge instead of overriding. I will edit the answer to make the distinction clearer. – VonC Apr 11 '19 at 04:33
  • @AkhilSurapuram I have edited the answer to emphasize the consequence of that `git checkout stash@{0} -- ` command. – VonC Apr 11 '19 at 06:29
  • In my Windows command prompt (git 2.36.0), `git restore --source='stash@{0}' -- ` returned an error: "fatal: could not resolve 'stash@{0}'". It required "stash@{0}" without single quotes. – Arkane May 31 '22 at 08:33
  • 1
    @Arkane Thank you for the feedback. I have edited the answer accordingly and remove the single quotes. – VonC May 31 '22 at 16:14
132
git checkout stash@{N} <File(s)/Folder(s) path> 

Eg. To restore only ./test.c file and ./include folder from last stashed,

git checkout stash@{0} ./test.c ./include
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Balamurugan A
  • 1,886
  • 2
  • 17
  • 19
  • 13
    This is the correct answer! Single line command to apply only stashed changes from specific files, works like a charm! – 4levels Jun 20 '14 at 13:23
  • 2
    To apply (just) the stashed changes for the file: "git diff stash@{N}^1 stash@{N} -- | git apply" – Vivek Oct 13 '16 at 07:19
  • This works for me too. Just selectively checkout the files needed to use from stash and you are done. I was stuck in this a I had used `-a` flag while creating the stash. – Rajeev Ranjan Oct 17 '17 at 18:18
  • 1
    @4levels I think "apply stashed changes" is not what happens, right? I think "overwrite whatever you have with the copy from stash" is what happens. – msouth Nov 05 '19 at 16:51
41

I think VonC's answer is probably what you want, but here's a way to do a selective "git apply":

git show stash@{0}:MyFile.txt > MyFile.txt
Mike Monkiewicz
  • 4,481
  • 1
  • 22
  • 19
  • 4
    This might be what you want in some cases, but beware that this command will **overwrite** rather than merge with any working directory changes. – Rhubbarb Nov 05 '15 at 12:06
  • This works for me, since I just wanted to copy a file that exists only in the stash and didn't care to `checkout` anything. – Tom Russell Oct 26 '16 at 05:33
  • 1
    For Windows PowerShell: `git show stash@\`{0\`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt` - the backticks are necessary for PS to not interpret the braces specially, and the `sc` is necessary [because PS's `>` operator defaults to UTF-16 (actually UCS-2)](https://stackoverflow.com/a/1709427/70345) which is probably not what you want. [@Balamurugan A's answer doesn't suffer from these issues.](https://stackoverflow.com/a/22555169/70345) – Ian Kemp Jun 09 '17 at 06:48
41

First list all the stashes

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Then show which files are in the stash (lets pick stash 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Then apply the file you like to:

git checkout stash@{1} -- <filename>

or whole folder:

git checkout stash@{1} /errors

It also works without -- but it is recommended to use them. See this post.

It is also conventional to recognize a double hyphen as a signal to stop option interpretation and treat all following arguments literally.

Black
  • 18,150
  • 39
  • 158
  • 271
  • 1
    I tried many ways and this way was the one I needed. I was faced with a problem that `git stash pop` thrown an error for untracked files. thank you. – Ramin Firooz Dec 23 '18 at 13:31
18

One more way:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
LachoTomov
  • 3,312
  • 30
  • 42
  • 4
    This is the only correct answer IMO. Using `checkout` or `show` will blindly overwrite your file instead of just applying changes. "One more way" is an understatement. – cambunctious Dec 08 '19 at 00:21
  • 3
    I'm not getting the `path/to/file2` as the you want to diff against the same file in your workspace. Leaving out the second path works fine for me. - And I get an error message using the `-R` option ("apply the patch in reverse", trying to patch the stashed version?!). So my working version looks like `git diff stash@{N}^! -- path/to/file | git apply -` . – ThomasH Jan 15 '20 at 15:36
  • 2
    "patch failed"? Try a 3-way merge. `...| git apply -3 -` – John Mee Jan 23 '20 at 22:41
  • `diff stash@{N}^!` already produces a forward diff, so omit `-R` – kxr Aug 20 '20 at 11:07
  • The ^! did not work in my case, so I ended up doing `git diff stash@{N} -- path/to/file | git apply -R` – Alwyn Schoeman Apr 16 '21 at 15:34
15

For Windows users: curly braces have special meaning in PowerShell. You can either surround with single quotes or escape with backtick. For example:

git checkout 'stash@{0}' YourFile

Without it, you may receive an error:

Unknown switch 'e'

Janac Meena
  • 3,203
  • 35
  • 32
13

If you git stash pop (with no conflicts) it will remove the stash after it is applied. But if you git stash apply it will apply the patch without removing it from the stash list. Then you can revert the unwanted changes with git checkout -- files...

Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
  • 2
    To clarify the conflicts part of this post, if you `git stash pop` and there ARE conflicts, you will have to fix them manually and the stash will NOT be removed. – theflowersoftime Sep 22 '16 at 19:00
4

For examle

git stash show --name-only

result

ofbiz_src/.project
ofbiz_src/applications/baseaccounting/entitydef/entitymodel_view.xml
ofbiz_src/applications/baselogistics/webapp/baselogistics/delivery/purchaseDeliveryDetail.ftl
ofbiz_src/applications/baselogistics/webapp/baselogistics/transfer/listTransfers.ftl
ofbiz_src/applications/component-load.xml
ofbiz_src/applications/search/config/elasticSearch.properties
ofbiz_src/framework/entity/lib/jdbc/mysql-connector-java-5.1.46.jar
ofbiz_src/framework/entity/lib/jdbc/postgresql-9.3-1101.jdbc4.jar

Then pop stash in specific file

git checkout stash@{0} -- ofbiz_src/applications/baselogistics/webapp/baselogistics/delivery/purchaseDeliveryDetail.ftl

other related commands

git stash list --stat
get stash show
Vy Do
  • 46,709
  • 59
  • 215
  • 313
3

For windows user to avoid Unknown switch 'e' the stash@{0} needs to surround inside quote as shown below

git restore --source='stash@{0}' -- <filename>

abdella
  • 490
  • 5
  • 11
0
git stash apply // apply all files
git reset . // reset all
git add <wanted_file> // add only wanted file(s)
git checkout . // negate changes of the other files
Jangwoong Kim
  • 121
  • 10
  • 2
    Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? **If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient.** Can you kindly [edit] your answer to offer an explanation? – Jeremy Caney Aug 30 '23 at 00:18