How do I stash only one file out of multiple files that have changed?
Asked Answered
P

33

3765

How do I stash only one of the multiple changed files on my branch?

Peta answered 14/6, 2010 at 20:52 Comment(3)
https://mcmap.net/q/11417/-how-do-i-stash-only-one-file-out-of-multiple-files-that-have-changed is much shorter than the accepted answer, does not need any additional tools (like e.g. JesusFreke's script) and it only stashes, what you wanted to stashCankerworm
>>>>>>>>> git diff -- *filename* > ~/patch then git checkout -- *filename* and later you can re-apply the patch with git apply ~/patchSgraffito
Most existing answers below are outdated. Since Git 2.13 (Q2 2017) it is supported with git stash push [--] [<pathspec>...].Handbarrow
S
3585
git stash push -p -m "my commit message"

-p let's you select the hunks that should be stashed; whole files can be selected as well.

You'll be prompted with a few actions for each hunk:

   y - stash this hunk
   n - do not stash this hunk
   q - quit; do not stash this hunk or any of the remaining ones
   a - stash this hunk and all later hunks in the file
   d - do not stash this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help
Sawyer answered 31/7, 2013 at 11:59 Comment(17)
@MatthieuNapoli are you sure? It's really fast and the help shows up at the top. q (quit)--don't stash the current hunk or any remaining a (all) -- this hunk, and all the ones after d (done-with-this-file) -- don't stash this hunk, or anything remaining in this file / (search) -- search for a hunk e (edit) -- manually edit current hunkCuisse
I am a TortoiseGit addict. However TortoiseGit does not support stash -p. I award this answer because it remains the most interactive/user friendly.Nikolas
you might want to add: git stash save -p my stash message; since the order of the argumenst is not very intuitive...Bobker
git stash -p does not support untracked files. For easier/frequent use, this simple script in my answer to a duplicate question allows you to specify which files to commit, and supports both tracked and untracked files.Ave
Between this and git log -p, I think the -p flag must mean "do the cool thing that I want but don't know how to express."Munificent
I repaired one of modified file (stash) with your answer, but after that I have an untracked files stashed.diffversion , what is that? what should I do?Thermoplastic
I handle it using git clean -fdThermoplastic
This is a correct answer, but it becomes unusable if you have too many hunks to work through.Sonority
A quick call out to answer posted on a newer question: https://mcmap.net/q/11613/-how-can-i-git-stash-a-specific-file by @svick git stash push -m <stash_name> <file_path_to_stash>Gourmandise
How can we pop a specific hunk back?Incensory
@Nikolas If you happen to use VSCode, it provides a GUI for stashing specific files by right clicking selected files in Source Control view and selecting Stash changes.Alverson
@Alverson that doesn't seem to be an option anymore... i have stage changes but not stash changes.Inhabitancy
@MaxCascone Strange, I have both right next to each other. Maybe GitLens extension adds that option??Alverson
@Alverson I didn't have the GitLens plugin installed at the time... now I do, and it's there. Nice!Inhabitancy
New added files are not showing in hunk selections. What to do for newly added files.?Vegetal
I screwed up a refactor that touched hundreds of files, and was not able to be undone from the IDE. This saved my branchInkerman
works but was very slowPrecept
M
1404

Disclaimer: the following answer is for git before git 2.13. For git 2.13 and over, check out another answer further down.


Warning

As noted in the comments, this puts everything into 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.


This will stash everything that you haven't previously added. Just git add the things you want to keep, then run it.

git stash --keep-index

For example, if you want to split an old commit into more than one changeset, you can use this procedure:

  1. git rebase -i <last good commit>
  2. Mark some changes as edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. Fix things up as necessary. Don't forget to git add any changes.
  7. git commit
  8. git stash pop
  9. Repeat, from #5, as necessary.
  10. git rebase --continue
Marlenmarlena answered 30/11, 2011 at 21:28 Comment(15)
I used this to split up some changes that were unrelated, using rebase -i, and it worked nicely. I added the files I wanted to work on, stash as above, fix things up as necessary, commit, stash pop, and repeat.Marlenmarlena
yep, i've just noted that in order to get to the original state - which is a clear staging area and with only some select unstaged modifications one could softly reset the index to get (without committing anything like you did). nevermind, and thanks for the info! :)Ocieock
This almost works well - it does not stash newly added files though. any solution for that?Cutback
I find this approach to be much more simpler: https://mcmap.net/q/11613/-how-can-i-git-stash-a-specific-fileDevindevina
I'm not sure why this is being upvoted. Everyone must have a different expectation than me. The original post is asking "how do I stash just a portion of the uncommitted changes?" When I use git stash save -k, yes the index (green in git stat) is preserved, but the entire changeset (both green and red) goes into the stash. This violates the OP's request, "stash only some changes". I want to stash just some of the red (for future usage).Computer
If you are more interested in the answer to the question posed by @Computer (as I was), then look here: #5506839Bouncing
@Raman: Excellent! git stash -p is exactly what I was looking for. I wonder if this switch was only recently added.Computer
I tried this and all the files were added to the stash, even the ones staged.Stentor
WARNING: git stash --keep-index is broken. If you make more changes, then try to git stash pop later you get merge conflicts because the stash includes the changed files you kept, not just the ones you didn't keep. For example: I change files A and B, then stash B, because I want to test the changes in A; I find a problem with A that I then fix; I commit A; Now I can't unstash because an old version of A is in the stash for no good reason causing a merge conflict. In practise A and B might be many files, perhaps even binary images or something, so I basically have to give up and lose B.Gerent
In addition to not answering the question, it is misleading. Saying "This will stash everything that you haven't previously added." suggests that when you "git add" some file, it will not be stashed. That is not the case. Can't understand why this is marked as the answer and has so many upvotes.Ressieressler
What is funny is that the other SO question in the link by @Raman, which answers the question more directly is marked as a duplicate of this :(Anabas
@Computer I suspect this answer was once correct but that the functionality was broken in some release of Git shortly after it was written. The Testing partial commits example at git-scm.com/docs/git-stash makes very clear that the intended behaviour of --keep-index is exactly what this answer claims, but as you point out, the actual behaviour is something different entirely. And yet it's gone unfixed for years! What a mess.Arsenite
ahaha unbelievable how the answer to a COMPLETELY different question than asked by OP can have +1000, lol :) The question was about git stash -pChaplain
this question wouldn't have been upvoted so massively if the right answer (git stash -p) wasn't so far to scroll (12th position for a moment). What is going on, SO? :)Chaplain
This is definitely NOT the right answer, using --keep-index won't stash just some files, it will stash ALL of your files.Albano
C
1031

Since Git 2.13 (Q2 2017), you can stash individual files, with git stash push:

git stash push [-m <message>] [--] [<pathspec>...]

When pathspec is given to 'git stash push', the new stash records the modified states only for the files that match the pathspec See "Stash changes to specific files" for more.

Simplified example:

 git stash push path/to/file

The test case for this feature shows a few more options off:

test_expect_success 'stash with multiple pathspec arguments' '
    >foo &&
    >bar &&
    >extra &&
    git add foo bar extra &&

    git stash push -- foo bar &&   

    test_path_is_missing bar &&
    test_path_is_missing foo &&
    test_path_is_file extra &&

    git stash pop &&
    test_path_is_file foo &&
    test_path_is_file bar &&
    test_path_is_file extra

The original answer (below, June 2010) was about manually selecting what you want to stash.

Casebash comments:

This (the stash --patch original solution) is nice, but often I've modified a lot of files so using patch is annoying

bukzor's answer (upvoted, November 2011) suggests a more practical solution, based on
git add + git stash --keep-index.
Go see and upvote his answer, which should be the official one (instead of mine).

About that option, chhh points out an alternative workflow in the comments:

you should "git reset --soft" after such a stash to get your clear staging back:
In order to get to the original state - which is a clear staging area and with only some select un-staged modifications, one could softly reset the index to get (without committing anything like you - bukzor - did).


(Original answer June 2010: manual stash)

Yet, git stash save --patch could allows you to achieve the partial stashing you are after:

With --patch, you can interactively select hunks from in the diff between HEAD and the working tree to be stashed.
The stash entry is constructed such that its index state is the same as the index state of your repository, and its worktree contains only the changes you selected interactively. The selected changes are then rolled back from your worktree.

However that will save the full index (which may not be what you want since it might include other files already indexed), and a partial worktree (which could look like the one you want to stash).

git stash --patch --no-keep-index

might be a better fit.


If --patch doesn't work, a manual process might:

For one or several files, an intermediate solution would be to:

  • copy them outside the Git repo
    (Actually, eleotlecram proposes an interesting alternative)
  • git stash
  • copy them back
  • git stash # this time, only the files you want are stashed
  • git stash pop stash@{1} # re-apply all your files modifications
  • git checkout -- afile # reset the file to the HEAD content, before any local modifications

At the end of that rather cumbersome process, you will have only one or several files stashed.

Capapie answered 14/6, 2010 at 21:23 Comment(9)
This is nice, but often I've modified a lot of files so using patch is annoyingDeviate
@Casebash: Then see my answer, below.Marlenmarlena
I don't quite get why I should perform a git reset --soft after the git stash --keep-index. A soft reset does not touch the index, so how does it make any difference as far as staging is concerned?Demagogic
@Kal: true, https://mcmap.net/q/11613/-how-can-i-git-stash-a-specific-file suggests a git reset (mixed)Capapie
git is fundamentally about managing a all repository content and index and not one or several files - that's implementation overshadowing the problem being solved; it's an explanation, but not a justification. Any source control system IS about "managing several files". Just look what comments get upvoted most.Bodice
-1 for recommending git stash --keep-index; as noted in the comments on bukzor's answer, it simply doesn't do what you think it does. Create two files, foo and bar. Commit them. Add a line to each. git add foo. git stash --keep-index. The desired result now is that you have your change to bar stashed, and your change to foo still present and staged. Reality is that you have your change to foo present and staged, but your changes to both files stashed. If you git reset and modify foo, you now cannot git stash pop due to conflict.Arsenite
This was crazy, at least commonsense has begun to prevail. Now I have to find out how to upgrade MacOSX Git to 2.13.Ricks
brew install gitGramarye
This also stashed all staged files. So make sure you haven't staged any changesLithia
C
125

Use git stash push, like this:

git stash push [--] [<pathspec>...]

For example:

git stash push -- my/file.sh

This is available since Git 2.13, released in spring 2017.

Clarkia answered 15/8, 2017 at 13:10 Comment(7)
But I do mention git stash push already in my answer above last March, 5 months ago. And I detailed that new Git 2.13 command here: https://mcmap.net/q/11620/-stash-changes-to-specific-files.Capapie
I'm happy that Git is advancing so quickly, for a long time this wasn't possible and then 2.13 is released and suddenly there is a simple solution available!Clarkia
@Capapie you're right, you also mention the correct answer, however, between the two answers, this one is easier to read (no confusing text and there is also an example). Maybe they should have edited your answer insteadMellicent
@Mellicent You had me at "you're right"... but yes, I have edited my answer to include an example.Capapie
Does one then use git stash apply to recover the stashed changes?Ruthful
Can anyone enlighten me as to why such an obscure word 'pathspec' is used to indicate file path? Or is it not so obscure as I think it is?Fredelia
@NikhilVandanapu I think the term pathspec is used because it can be more than a simple path. It can include the standard wildcards, double-asterisk wildcards and even more esoteric syntax. For more info, go to https://git-scm.com/docs/gitglossary and search for pathspec.Erector
P
94

When git stash -p (or git add -p with stash --keep-index) would be too cumbersome, I found it easier to use diff, checkout and apply:

To "stash" a particular file/dir only:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

Then afterwards

git apply stashed.diff
Progesterone answered 12/2, 2014 at 13:44 Comment(5)
Interesting alternative to the git add -p I mentioned in my own answer above. +1.Capapie
Note that if you have binary files (like PNGs) they won't be output to the diff file. So this isn't a 100% solution.Effeminacy
@RobertDailey: That's an interesting point to me, as git diff > file.diff and git apply are my usual partial stash tools. I may have to consider switching to git stash -p for larger changesets.Suggest
@Suggest Here is the alias I use to create patch files, and it does support binaries: patch = log --pretty=email --patch-with-stat --reverse --full-index --binary. Note, however, this requires your changes for the patch to be committed.Effeminacy
This was not working cleanly for me if the file to stash was something like ../../foo/bar.txt. The patch generates OK, but I then need to move to the repository root to get the patch to apply. So if you're having trouble with this - just make sure you're doing it from the repository root directory.Erinaceous
B
62

If you do not want to specify a message with your stashed changes, pass the filename after a double-dash.

$ git stash -- filename.ext

If it's an untracked/new file, you will have to stage it first.

This method works in git versions 2.13+

Beauchamp answered 9/3, 2019 at 4:1 Comment(2)
That answer is verbose, this is concise. If it helps someone, I will leave it. No one on this page mentions this syntax and result - they instead mention ` git stash push`.Beauchamp
This is the answer I was looking for. Thanks! +1Steiger
F
58

Let's say you have 3 files

a.rb
b.rb
c.rb

and you want to stash only b.rb and c.rb but not a.rb

you can do something like this

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

And you are done! HTH.

Fy answered 31/10, 2013 at 7:10 Comment(0)
C
40

If you want to stash only some of changed files, simply just Add other files in the Stage, Then execute git stash push --keep-index

It will stash all unstaged changed files

Consanguinity answered 12/12, 2019 at 7:8 Comment(1)
This is not correct. --keep-index has no effect on what's captured in the stash. It simply leaves staged files as staged in the working tree plus the stash will keep information of what files were stashed. Then if you want to actually have that info back in your working tree, you need to pop/apply with --index. Otherwise the info on what was staged and what not is disregarded and everything is restored as unstaged.Wynny
O
31

Another way to do this:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply stash@{1}
git stash drop stash@{1}

git checkout <"files you put in your stash">

I came up with this after I (once again) came to this page and didn't like the first two answers (the first answer just doesn't answer the question and I didn't quite like working with the -p interactive mode).

The idea is the same as what @VonC suggested using files outside the repository, you save the changes you want somewhere, remove the changes you don't want in your stash, and then re-apply the changes you moved out of the way. However, I used the git stash as the "somewhere" (and as a result, there's one extra step at the end: removing the cahnges you put in the stash, because you moved these out of the way as well).

One answered 5/2, 2015 at 10:16 Comment(3)
i prefer this approach most. It provides an easy workflow in tortoisegit using only stash and revert commands.Nonobedience
Referring to answers on SO using positions is not advisable. Positions change as ratings change.Cadenza
@BryanAsh Well, it's not like it matters here. I am giving an anecdote rather than really referring to the other answers. The message is that I didn't like the answers the community liked and not what these answers actually contain. Besides, the 900 vote gap between the second and third answer make this unlikely to change in the near future, and if it should ever change I can always edit it to say "the top to answers at the time". Really, I don't see how this is any sort of problem in this situation.One
L
30

You can simply do this:

git stash push "filename"

or with an optional message

git stash push -m "Some message" "filename"
Leaven answered 21/5, 2019 at 5:3 Comment(2)
This adds nothing new. Git stash push is already mentioned in multiple answersInandin
The git stash push -- <filepath> was what worked for me and is added in recent GIT version (v2.13>) as the way to go. You can get the <filepath> if you run a git status.Epenthesis
I
23

Update (2/14/2015) - I've rewritten the script a bit, to better handle the case of conflicts, which should now be presented as unmerged conflicts rather than .rej files.


I often find it more intuitive to do the inverse of @bukzor's approach. That is, to stage some changes, and then stash only those staged changes.

Unfortunately, git doesn't offer a git stash --only-index or similar, so I whipped up a script to do this.

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

You can save the above script as git-stash-index somewhere on your path, and can then invoke it as git stash-index

# <hack hack hack>
git add <files that you want to stash>
git stash-index

Now the stash contains a new entry that only contains the changes you had staged, and your working tree still contains any unstaged changes.

In some cases, the working tree changes may depend on the index changes, so when you stash the index changes, the working tree changes have a conflict. In this case, you'll get the usual unmerged conflicts that you can resolve with git merge/git mergetool/etc.

Inandin answered 16/6, 2013 at 21:0 Comment(2)
Recommend pushd instead of cd and popd at the end of the script so if the script succeeds, the user ends up in the same directory as before running it.Annuitant
@Nate: as far as I know, it should only change the directory for the user if they sourced the script. If you run the script normally (~/bin/git-stash-index), or via git (git stash-index), it gets run in a separate terminal session, and any working directory changes in that session don't affect the working directory in the user's terminal session. Are you aware of a common usage case when this is not true? (other than sourcing the script, which I wouldn't consider "common")Inandin
U
21

Since creating branches in Git is trivial you could just create a temporary branch and check the individual files into it.

Unchristian answered 28/6, 2011 at 12:7 Comment(3)
You can't create a branch with unstaged edits. You can easily move all the edits to a new branch (stash/stash pop) but then you're back to square one: how do you test your branch with only some of those edits, without losing the others?Marlenmarlena
You can't switch branches if you have local changes. However, you can create a new branch and selectively add/commit files, and then create another branch and do the same recursively... then checkout the original branch and selectively merge back in. I just did it. It actually seems the natural way to do things, as you're essentially creating feature branches.Siam
@iain you can switch branches if you have local changes, as long as they don't require a merge. See Example Gist. This is true as of Git v2.7.0 at least.Percolate
D
14

Just in case you actually mean discard changes whenever you use git stash (and don't really use git stash to stash it temporarily), in that case you can use

git checkout -- <file>

[NOTE]

That git stash is just a quicker and simple alternative to branching and doing stuff.

Dvinsk answered 19/12, 2014 at 11:40 Comment(0)
P
12

Save the following code to a file, for example, named stash. Usage is stash <filename_regex>. The argument is the regular expression for the full path of the file. For example, to stash a/b/c.txt, stash a/b/c.txt or stash .*/c.txt, etc.

$ chmod +x stash
$ stash .*.xml
$ stash xyz.xml

Code to copy into the file:

#! /usr/bin/expect --
log_user 0
set filename_regexp [lindex $argv 0]

spawn git stash -p

for {} 1 {} {
  expect {
    -re "diff --git a/($filename_regexp) " {
      set filename $expect_out(1,string)
    }
    "diff --git a/" {
      set filename ""
    }
    "Stash this hunk " {
      if {$filename == ""} {
        send "n\n"
      } else {
        send "a\n"
        send_user "$filename\n"
      }
    }
    "Stash deletion " {
      send "n\n"
    }
    eof {
      exit
    }
  }
}
Petronia answered 11/7, 2014 at 18:55 Comment(1)
Great method. I would have picked this as the answer. Tip for future readers: you have to match on the full path. e.g. stash subdir/foo.cTinaret
P
10

The problem with VonC's `intermediate' solution of copying files to outside the Git repo is that you lose path information, which makes copying a bunch of files back later on somewhat of a hassle.

A find it easier to use tar (similar tools will probably do) instead of copy:

  • tar cvf /tmp/stash.tar path/to/some/file path/to/some/other/file (... etc.)
  • git checkout path/to/some/file path/to/some/other/file
  • git stash
  • tar xvf /tmp/stash.tar
  • etc. (see VonC's `intermediate' suggestion)
Pokeberry answered 27/9, 2011 at 13:21 Comment(1)
checkout -f is not needed, checkout (without -f) is enough, I've updated the answer.Pokeberry
R
9

I would use git stash save --patch. I don't find the interactivity to be annoying because there are options during it to apply the desired operation to entire files.

Rigby answered 13/4, 2017 at 16:1 Comment(2)
Amazed there's so little backing for this answer, it's best solution without need for an essay.Higgle
Definitely the good answer, git stash -p permits you to stash a whole file rapidly and quitting afterwards.Whisker
E
8

Sometimes I've made an unrelated change on my branch before I've committed it, and I want to move it to another branch and commit it separately (like master). I do this:

git stash
git checkout master
git stash pop
git add <files that you want to commit>
git commit -m 'Minor feature'
git stash
git checkout topic1
git stash pop
...<resume work>...

Note the first stash & stash pop can be eliminated, you can carry all of your changes over to the master branch when you checkout, but only if there are no conflicts. Also if you are creating a new branch for the partial changes you will need the stash.

You can simplify it assuming no conflicts and no new branch:

git checkout master
git add <files that you want to commit>
git commit -m 'Minor feature'
git checkout topic1
...<resume work>...

Stash not even needed...

Effeminacy answered 13/3, 2014 at 14:19 Comment(0)
H
8

This can be done easily in 3 steps using SourceTree.

  1. Temporarily commit everything you don't want stashed.
  2. Git add everything else, then stash it.
  3. Pop your temporary commit by running git reset, targetting the commit before your temporary one.

This can all be done in a matter of seconds in SourceTree, where you can just click on the files (or even individual lines) you want to add. Once added, just commit them to a temporary commit. Next, click the checkbox to add all changes, then click stash to stash everything. With the stashed changes out of the way, glance over at your commit list and note the hash for the commit before your temporary commit, then run 'git reset hash_b4_temp_commit', which is basically like "popping" the commit by resetting your branch to the commit right before it. Now, you're left with just the stuff you didn't want stashed.

Houck answered 11/1, 2016 at 19:41 Comment(0)
T
8

Every answer here is so complicated...

What about this to "stash":

git diff /dir/to/file/file_to_stash > /tmp/stash.patch
git checkout -- /dir/to/file/file_to_stash

This to pop the file change back:

git apply /tmp/stash.patch

Exact same behavior as stashing one file and popping it back in.

Tuscarora answered 14/12, 2016 at 20:19 Comment(2)
I tried it but nothing happens. When I git apply I have no error but changes are not brought back neitherElihu
The patch file you generated in /tmp was probably deleted. You might have rebooted between the diff and the apply. Try another more permanent location. It does work. Also check the contents of the patch file.Tuscarora
A
6

I've reviewed answers and comments for this and a number of similar threads. Be aware that none of the following commands are correct for the purpose of being able to stash any specific tracked/untracked files:

  • git stash -p (--patch): select hunks manually, excluding untracked files
  • git stash -k (--keep-index): stash all tracked/untracked files and keep them in the working directory
  • git stash -u (--include-untracked): stash all tracked/untracked files
  • git stash -p (--patch) -u (--include-untracked): invalid command

Currently, the most reasonable method to be able to stash any specific tracked/untracked files is to:

  • Temporarily commit the files you don't want to stash
  • Add and stash
  • Pop the temporary commit

I wrote a simple script for this procedure in an answer to another question, and there are steps for performing the procedure in SourceTree here.

Ave answered 22/3, 2017 at 4:36 Comment(0)
C
4

When you try to switch between two branches, this situation occurs.

Try to add the files using "git add filepath".

Later execute this line

git stash --keep-index

Caloric answered 21/7, 2015 at 19:26 Comment(0)
T
4

Solution

Local changes:

  • file_A (modified) not staged
  • file_B (modified) not staged
  • file_C (modified) not staged

To create a stash "my_stash" with only the changes on file_C:

1. git add file_C
2. git stash save --keep-index temp_stash
3. git stash save my_stash
4. git stash pop stash@#{1}

Done.


Explanation

  1. add file_C to the staging area
  2. create a temporary stash named "temp_stash" and keep the changes on file_C
  3. create the wanted stash ("my_stash") with only the changes on file_C
  4. apply the changes in "temp_stash" (file_A and file_B) on your local code and delete the stash

You can use git status between the steps to see what is going on.

Tyranny answered 29/3, 2017 at 15:4 Comment(0)
W
4

To stash a single file use git stash --patch [file].

This is going to prompt: Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ?. Just type a (stash this hunk and all later hunks in the file) and you're fine.

Weekender answered 14/9, 2018 at 19:22 Comment(2)
Missing push as in git stash push --patch [file]Dulciana
@FilipeEsperandio push only works in more recent versions of Git, used to be save. In either case push or save are implied by calling stash: "Calling git stash without any arguments is equivalent to git stash push", docsWaistcloth
R
3

Similar situation. Did commit and realized it's not ok.

git commit -a -m "message"
git log -p

Based on the answers this helped me.

# revert to previous state, keeping the files changed
git reset HEAD~
#make sure it's ok
git diff
git status
#revert the file we don't want to be within the commit
git checkout specs/nagios/nagios.spec
#make sure it's ok
git status
git diff
#now go ahead with commit
git commit -a -m "same|new message"
#eventually push tu remote
git push
Recognizee answered 20/6, 2012 at 6:49 Comment(0)
C
2

In this situation I git add -p (interactive), git commit -m blah and then stash what's left if necessary.

Califate answered 18/4, 2013 at 21:10 Comment(0)
I
2

I don't know how to do it on command line, only using SourceTree. Lets say you have changed file A, and have two change hunks in file B. If you want to stash only the second hunk in file B and leave everything else untouched, do this:

  1. Stage everything
  2. Perform changes to your working copy that undo all the changes in file A. (e.g. launch external diff tool and make files match.)
  3. Make file B look as if only second change is applied to it. (e.g. launch external diff tool and undo first change.)
  4. Create a stash using "Keep staged changes".
  5. Unstage everything
  6. Done!
Inn answered 30/4, 2015 at 11:15 Comment(0)
S
2
git add .                           //stage all the files
git reset <pathToFileWillBeStashed> //unstage file which will be stashed
git stash                           //stash the file(s)
git reset .                         // unstage all staged files
git stash pop                       // unstash file(s)
Sarcastic answered 20/7, 2018 at 10:46 Comment(3)
Well, you should not do that. The Answer should provide a solution to the question. You could just ask your own question.Tiaratibbetts
this solution is one of the easiest answer for the THIS question. read question, compare all the answers and mine then if you have any doubt that this answer neither a applicable solution nor insufficient information about the question, then we can talk again.Sarcastic
This will not work, because third command, "git stash" will not honour staged files. Both, staged and nonstaged files will go to the stash. The questions specifically asks how to stash only one fileCalender
B
1

I found no answer to be what I needed and that is as easy as:

git add -A
git reset HEAD fileThatYouWantToStash
git commit -m "committing all but one file"
git stash

This stashes exactly one file.

Budde answered 27/2, 2017 at 8:39 Comment(0)
R
0

One complicated way would be to first commit everything:

git add -u
git commit // creates commit with sha-1 A

Reset back to the original commit but checkout the_one_file from the new commit:

git reset --hard HEAD^
git checkout A path/to/the_one_file

Now you can stash the_one_file:

git stash

Cleanup by saving the committed content in your file system while resetting back to the original commit:

git reset --hard A
git reset --soft HEAD^

Yeah, somewhat awkward...

Rooney answered 8/2, 2017 at 18:17 Comment(0)
C
0

For users of VS Code. The stash button for the Changes group in the Git sidebar view will stash only the files in the group. So if you move some files out of that group, you can then stash the remaining files. The only way I know of moving some files out of there without reverting the changes is to stage them. So:

  1. Stage the files you don't want to stash
  2. Click the stash button in the Changes group header
  3. Unstage the files you moved out of the way
Coupler answered 27/5, 2021 at 14:24 Comment(0)
C
0

Currently (2024), GiT is providing a much simpler way to achieve this using the new --staged option:

git add <some-files>                  # pick (stage) the files to stash
git stash save --staged 'my stash'    # stash only staged

To my suprise, among all the answers nobody prodided the solution for recent GiT versions (>= 2.35) on how to stage only specific files out of many unstaged changes.

Coalfish answered 3/4 at 15:1 Comment(0)
C
-1

You can also choose to stash just a single file, a collection of files, or individual changes from within files. If you pass the -p option (or --patch) to git stash, it will iterate through each changed "hunk" in your working copy and ask whether you wish to stash it:

$ git stash -p

press one of the key as below and it will run that command

Command   Description 
y         stash this hunk  
/         search for a hunk by regex .  
?         help .   
n         don't stash this hunk .    
q         quit (any hunks that have already been selected will be stashed) .   
s         split this hunk into smaller hunks    
Czernowitz answered 25/2, 2020 at 9:47 Comment(1)
B
-1

I wanted to do the same thing as well, but when I thought about it again, I realized that I don't really want to go with all the hassle to just keep one file. It would be much easier for me to copy it to somewhere else and add some comments to remind me why I kept it there.

Don't get me wrong: there are tons of reasons why you would like to just stash a single file, and in general, utilizing version control software is always the best practice. But still, make sure you are not wasting your time. In my case, I just wanted to keep a file and discard all other changes, and pop it after I switch to a new branch. So cp/mv worked well enough.

But answered 23/4, 2020 at 16:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.