Question
How do I stash only one file out of multiple files that have changed?
How do I stash only one of the multiple changed files on my branch?
Question
How do I stash only one of the multiple changed files on my branch?
Solution
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
Solution
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:
git rebase -i <last good commit>
edit
.git reset HEAD^
git add <files you want to keep in this change>
git stash --keep-index
git add
any changes.git commit
git stash pop
git rebase --continue
Solution
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:
git stash
git stash
# this time, only the files you want are stashedgit stash pop stash@{1}
# re-apply all your files modificationsgit checkout -- afile
# reset the file to the HEAD content, before any local modificationsAt the end of that rather cumbersome process, you will have only one or several files stashed.
Solution
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.
Solution
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
Solution
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+
Solution
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.
Solution
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
Solution
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).
Solution
You can simply do this:
git stash push "filename"
or with an optional message
git stash push -m "Some message" "filename"
Solution
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.
Solution
Since creating branches in Git is trivial you could just create a temporary branch and check the individual files into it.
Solution
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.
Solution
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
}
}
}
Solution
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:
Solution
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.
Solution
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...
Solution
This can be done easily in 3 steps using SourceTree.
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.
Solution
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.
Solution
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 provided the solution for recent Git versions (>= 2.35) on how to stage only specific files out of many unstaged changes.
Solution
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 filesgit stash -k (--keep-index)
: stash all tracked/untracked files and keep them in the working directorygit stash -u (--include-untracked)
: stash all tracked/untracked filesgit stash -p (--patch) -u (--include-untracked)
: invalid commandCurrently, the most reasonable method to be able to stash any specific tracked/untracked files is to:
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.
Solution
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
Solution
Local changes:
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.
You can use git status between the steps to see what is going on.
Solution
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.
Solution
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
Solution
In this situation I git add -p
(interactive), git commit -m blah
and then stash what's left if necessary.
Solution
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:
Solution
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)
Solution
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.
Solution
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...