2316

How can I stash a specific file leaving the others currently modified out of the stash I am about to save?

For example, if git status gives me this:

younker % gst      
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   app/controllers/cart_controller.php
#   modified:   app/views/cart/welcome.thtml
#
no changes added to commit (use "git add" and/or "git commit -a")

and I only want to stash app/views/cart/welcome.thtml, how would I do that? Something like (but of course this does not work):

git stash save welcome_cart app/views/cart/welcome.thtml
Cœur
  • 37,241
  • 25
  • 195
  • 267
ynkr
  • 25,946
  • 4
  • 32
  • 30

14 Answers14

3251

EDIT: Since git 2.13, there is a command to save a specific path to the stash: git stash push <path>. For example:

git stash push -m welcome_cart app/views/cart/welcome.thtml

OLD ANSWER:

You can do that using git stash --patch (or git stash -p) -- you'll enter interactive mode where you'll be presented with each hunk that was changed. Use n to skip the files that you don't want to stash, y when you encounter the one that you want to stash, and q to quit and leave the remaining hunks unstashed. a will stash the shown hunk and the rest of the hunks in that file.

Not the most user-friendly approach, but it gets the work done if you really need it.

piet.t
  • 11,718
  • 21
  • 43
  • 52
svick
  • 236,525
  • 50
  • 385
  • 514
  • 6
    The only thing this doesn't seem to do is include changes to binary filed. I edited some graphics, did the git stash --patch method and they were never listed. – Jeremy Ricketts Jun 18 '12 at 18:39
  • 41
    Cumbersome, but works. I wish there was a quick way to stash only staged changes, and then have the changes go into the unstaged working tree when it's later popped. – James Johnston Sep 26 '12 at 14:42
  • 74
    @JamesJohnston `git stash --keep-index` will allow you to stash all the unstaged changes (the opposite of what you're looking for). http://stackoverflow.com/a/8333163/378253 – nimser Oct 16 '13 at 11:23
  • 128
    If you say `a` instead of `y` it will stash that hunk + the remainder of the file, which is much faster. – i_am_jorf Nov 21 '13 at 21:39
  • 53
    @jeffamaphone great! also `d` will do the opposite, i.e. not stash any further hunks in the current file. and indeed `?` will show all possible options. – omnikron Dec 05 '13 at 11:15
  • 1
    @svick, it got stuck when `git push -p`, no response. – hiway Jun 06 '14 at 08:39
  • 7
    Thanks! [Command](http://git-scm.com/docs/git-stash) that I used is: `git stash save --patch "Stash message"`, which then I entered the [**Interactive Mode**](http://git-scm.com/docs/git-add.html) to select the hunks that I will stash. I could also use this command: `git stash save --patch --no-keep-index "Stash message"` when I already staged the files I wanted to stash and doesn't want to keep it in after stashing. – KarenAnne Jun 11 '14 at 10:04
  • 2
    `--patch` **is** user friendly! – lajarre Jul 16 '14 at 09:23
  • @NicolasWormser `git stash --keep-index` is broken. Read the comments on [this answer](http://stackoverflow.com/a/8333163/711807). –  Nov 11 '14 at 05:41
  • @svick How can i `git stash -p` with newly staged files (e. g. `new file: test.txt`). – steffen Apr 27 '15 at 14:45
  • 6
    I wanted to use this but give the Stash a name. The order of parameters is quite sensitive - e.g. neither of `git stash -p save "name"` nor `git stash save "name" -p` worked but finally found that **`git stash save -p "name"`** *did* work. – Steve Chambers Jul 13 '15 at 08:19
  • @ZimbiX If you think you have a better answer, I think you should post an answer to the question this one is marked as duplicate of (http://stackoverflow.com/questions/3040833/stash-only-one-file-out-of-multiple-files-that-have-changed-with-git), not edit mine. – svick Mar 21 '17 at 00:51
  • @svick Sorry, I thought it was important information to include and didn't have the reputation to comment yesterday. – ZimbiX Mar 22 '17 at 04:45
  • So yeah, I've posted those details now [in an answer to the duplicate](http://stackoverflow.com/a/42942825/1239774). Simply put, `git stash -p` does not support untracked files. [This simple script in my answer to another more specific question](http://stackoverflow.com/a/42916031/1239774) allows you to specify which files to commit, **supports both tracked and untracked files**, and is easier for frequent use. – ZimbiX Mar 22 '17 at 04:55
  • 3
    The edit in v2.13 is EXACTLY what this question requires. – jimh Dec 18 '17 at 21:06
  • 2
    also `-u` option allows to stash new, not already committed, file – Juh_ Jun 28 '19 at 12:28
  • Try this command: `git stash push -- path/to/file.py` – Tomiwa Jul 15 '19 at 16:04
  • 1
    if it's a new file, add the `--include-untracked` option like this `git stash push --include-untracked path/to/file.py` – Madacol Jul 22 '19 at 16:25
  • 2
    What does `-m` do ? – Vencovsky Aug 05 '19 at 15:05
  • 16
    @Vencovsky It stands for "message" and is used to specify optional description of the stash. If you don't need that, you can leave the `-m welcome_cart` part out. – svick Aug 05 '19 at 16:22
  • 3
    FYI, popping this stashed file is done the same way as usual, git stash pop – n00b Aug 26 '19 at 21:10
  • 2
    @svick Might be worth updating the answer to clarify what the `-m` is doing, I (wrongly) assumed that you were listing different file paths after that, and so my path ended up getting added as a message instead of part of the stash :) – nbrooks Apr 09 '20 at 16:21
  • No one got an equivalent for this for 2.7.4? :( – oarfish Jul 03 '20 at 09:06
  • 1
    This also works for multiple files: `git stash push -m temp /file/one /file/two /file/three` – jbaranski Apr 01 '21 at 15:30
  • in Sourcetree app, you can leave the target files in "Unstaged files" and do "Stash Changes..." command, make sure check "Keep staged changes". – Honghao Z Jun 15 '21 at 23:02
386

I usually add to index changes I don't want to stash and then stash with --keep-index option.

git add app/controllers/cart_controller.php
git stash --keep-index
git reset

The last step is optional, but usually, you want it. It removes changes from the index.


Warning As noted in the comments, git stash --keep-index pushes everything onto the stash, both staged and unstaged. The --keep-index just leaves the index alone after the stash is done. This can cause merge conflicts when you later pop the stash.

Anton Menshov
  • 2,266
  • 14
  • 34
  • 55
skalee
  • 12,331
  • 6
  • 55
  • 57
  • 5
    This is much better than the accepted answer if you have a lot changes you don't want to wade through with the --patch option. – quux00 Dec 21 '12 at 15:36
  • 207
    No, this puts everything into the stash, both staged and unstaged. The `--keep-index` just leaves the index alone after the stash is done. So this isn't a valid answer to the question, AFAICT. – Raman Mar 17 '13 at 19:22
  • 3
    See my answer on @Rachel's question for a solution to doing the inverse of this (stashing the staged changes, instead of the unstaged changes) - http://stackoverflow.com/questions/3040833/how-to-stash-only-one-file-out-of-multiple-files-that-have-changed/17137669#17137669 – JesusFreke Jun 16 '13 at 21:06
  • 3
    After, if you want to get back the files you stashed without committing the files you added, you can run `git stash; git stash pop stash@{1}`. – yndolok Nov 20 '13 at 21:07
  • 8
    WARNING: Take note of @Raman's point. This doesn't do what it should. This will put the same changes in the stash **and** leave them in the working tree. When you later try to pop the stash, you are likely to get merge conflicts, and they are often really confusing and hard to fix. – rjmunro Apr 08 '14 at 10:23
  • 2
    @DanBerindei The staged files stayed in the index **and** went in the stash. If you edit one of them and try to unstash, you will often get an edit conflict. If you discard the changes to those files and unstash, the changes will come back - at least that's what happened last time I tried it. – rjmunro May 16 '14 at 23:21
234

For stashing one file:

git stash -- filename.txt

To give a message in the command rather than enter it when prompted, add -m before the file part, e.g. git stash -m "stash-message" -- filename1.txt

For stashing more than one file:

git stash -m "stash-message" -- filename1.txt filename2.txt…
greybeard
  • 2,249
  • 8
  • 30
  • 66
HongchaoZhang
  • 3,494
  • 1
  • 17
  • 8
  • 3
    This only works for tracked files, otherwise you get an error like: `error: pathspec 'filename1' did not match any file(s) known to git` – Nico Brenner Aug 16 '22 at 16:53
  • this one worked fine with tracked files.+1, worked for me. – Alive to die - Anant Oct 17 '22 at 05:03
  • 1
    This worked for me as the fastest and simplest solution to OP's problem, +1 – noxter Dec 05 '22 at 11:16
  • 8
    For stashing with a message add `-m` before file part, e.g. `git stash -m "your message" -- filename1.txt filename2.txt` – Fenix Jan 12 '23 at 16:48
  • 1
    You can also stash untracked files by adding them to the staging area, e.g., `git add my.file` and then `git stash -- my.file`. And whenever you apply the stash changes, if you want, you can unstage them, so they remain untracked again. – DonLarry Feb 27 '23 at 04:50
  • Did not work on centos7 git version 1.8.3.1 – wxz Apr 28 '23 at 19:54
169

To add to svick's answer, the -m option simply adds a message to your stash, and is entirely optional. Thus, the command

git stash push [paths you wish to stash]

is perfectly valid. So for instance, if I want to only stash changes in the src/ directory, I can just run

git stash push src/
dlq
  • 2,743
  • 1
  • 12
  • 12
  • 4
    NB: Popping is done _without_ the path, just `git stash pop`. – Olle Härstedt Apr 28 '21 at 15:58
  • This command is much more efficient than the `--keep-index` suggestion above which requires multiple commands, and is a bit counter-intuitive (adding the files you **don't** want to stash). – stwr667 Aug 24 '22 at 01:17
48

If you are using visual studio code there is a simpler way to stash selected files.

  1. Make sure you have installed GitLens extension in VSCode
  2. Go to Source Control tab
  3. Select files those you want to stash
  4. Right click on it, you will see many options. Click on Stash Changes

enter image description here

  1. Now it will ask you to add some stash message. Add understandable message and hit enter.

enter image description here

Akshay
  • 926
  • 9
  • 21
13
  • git status (make sure your changes that can stash)

src/config/bl.go

src/config/dl.go

If you want to stash only dl.go

  • git stash push -m "< enter your msg eg:dl files reverted> " src/config/dl.go

Show your stash list

  • git stash list

Then checkout your branch and apply stash

  • git stash apply stash{0}
Omkesh Sajjanwar
  • 575
  • 8
  • 13
12

Short and Simple solution:

git stash -- finename.ext

in your case git stash -- app/views/cart/welcome.thtml

Vicky P
  • 553
  • 6
  • 12
5

If you're OK with using a GIT GUI client, Fork can pretty seamlessly do this as of May 2020. A GIF of the partial stash functionality will show this better than any words: GIF of partial stash functionality in git-fork

Note that Fork (which is a difficult name to Google for!) is not free software and costs $50 after the evaluation period, but you can just ignore the popups like you do for WinRAR or WinZip.

georgiecasey
  • 21,793
  • 11
  • 65
  • 74
4
  1. stage the changes you do NOT want to stash.
  2. stash the remaining unstaged files with:
$ git stash save <give_it_a_name> --keep-index

The unstaged files are now stashed. See the stash list with your named stash:

$ git stash list

stash@{0}: On mybranch: WIP220412-1119am
stash@{1}: On mybranch: WIP220312-749am

To restore the stashed files:

$ git stash apply stash@{<index_of_saved_stash>}
$ git stash apply stash@{0}

The changes stashed in WIP220412-1119am are now restored. And the stash list remains as well, (instead of "git stash pop", you can retain the list this way.)

Brent Worden
  • 10,624
  • 7
  • 52
  • 57
  • This only works for changed files I guess? If you want to add a new file to a stash you need to stage it first, which doesn't work with the `--keep-index` flag. – Koen May 11 '22 at 08:05
4

@svick has posted a great answer. I wanted to stash all my .java files and leave build.gradle untouched so I ran:

git stash push *.java
Justin
  • 367
  • 2
  • 14
1

I think using git stash push <path> will be nice! it also supports patterns.

  • eg. git stash push welcome.*ml will stash any start with welcome. and end with ml files. This is suitable for you.
scott
  • 71
  • 1
  • 3
1

Since git 2.35.0 you can stash staged changes using --staged | -S flag.

For instance:

git stash --staged

--staged

This option is only valid for push and save commands.

Stash only the changes that are currently staged. This is similar to basic git commit except the state is committed to the stash instead of current branch.

The --patch option has priority over this one.

https://git-scm.com/docs/git-stash/2.35.0#Documentation/git-stash.txt---staged

The nice part about this new feature is that not only it's possible to stash specific untracked files, but also it's possible to stash specific part of the code changes in tracked files; when you add those to stage using --patch | -p flag.

Omid
  • 51
  • 6
0

My preferred method (the easiest in my opinion) is simply:

git stash -- <path/to/directory>

or

git stash -- path/to/directory/file.py

Matt C.
  • 2,330
  • 3
  • 22
  • 26
-2

In Source Control tab of vs-code, hold shift key and then select the files you want to stash, then right click and choose stash changes option.