How to stash only unstaged changes in Git?
Solution 1
From Git 2.35+ (Q1 2022) you can now use the --staged flag (man) on git stash push to only stage the changes in your index.
Since your question asks the exact opposite, we have 2 choices:
- Reverse the operation like so:
git stash push --staged # Stash staged changes
git stash # Stash everything else
git stash pop stash@{1} # Restore staged changes stash
- Stage the changes you want to stash instead of the ones you want to keep. Now you can just run:
git stash push --staged
I got this information from this answer on another S/O post.
Solution 2
git stash push has an option --keep-index that does exactly what you need.
So, run git stash push --keep-index.
Solution 3
This may be done in 3 steps: save staged changes, stash everything else, restore index with staged changes. Which is basically:
git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^
This will do exactly what you want.
Solution 4
git stash save --keep-index
Also, Re:
Why not commit your changes after staging them? – Shin
A: Because you should always checkin tested code :) That means, you need to run the tests with only the changes you are about to commit
All this apart from the fact that of course, as an experienced programmer, you have the innate urge to test and review just those changes -- only partly kidding
Solution 5
Stash Without the Staged Changes
The Problem with --keep-index / -k
Stashing just the working tree (unstaged changes) in Git is more difficult than it should be. The accepted answer, and quite a few other answers, stashes the unstaged changes and leaves the stage alone as requested via --keep-index.
However what isn't obvious is that --keep-index also stashes the staged changes. The staged changes end up in both the stage AND the stash. This is rarely what one wants because any interim changes to the stash are likely to result in conflicts when popping the stash later.
Alias Solution
This alias works well to stage just the working copy changes:
stash-working = "!f() { \
git commit --quiet --no-verify -m \"temp for stash-working\" && \
git stash push \"$@\" && \
git reset --quiet --soft HEAD~1; }; f"
It commits the staged changes temporarily, creates a stash from the remaining changes (and allows additional arguments such as --include-untracked and --message to be passed as alias arguments), and then resets the temporary commit to get back the staged changes.
It is similar to @Simon Knapp's answer, but with a few minor differences -- it uses --quiet on the temporary actions taken, and it accepts any number of parameters for the stash push, rather than hard-coding the -m, and it does add --soft to the final reset so that the index remains as it started. It also uses --no-verify on the commit to avoid changes to the working copy from pre-commit hooks (HT: @Granfalloner).
For the opposite problem of stashing just the staged changes (alias stash-index) see this answer.
Related videos on Youtube
Unapiedra
Updated on February 23, 2022Comments
-
Unapiedra over 1 yearI would like to use this workflow:
- Stage some changes.
- Save the unstaged changes to the stash.
- Do some stuff with the things in stage (build, test, etc.).
- Commit.
- Restore the unstaged changes.
Is there a way to do step 2?
Example:
git init echo one >file git add file git commit echo two >>file git add file echo three >>file git stash push test git commit git stash pop-
Shizzmo over 11 yearsWhy not commit your changes after staging them? -
sehe over 11 yearsIIRC --keepindex does exactly that -
Unapiedra over 11 yearsBecause if, say, the build fails I don't want to have a commit of this. I know I can delete the commit but I'd like to do this without a commit if possible. -
Unapiedra over 11 yearsSehe, thanks. I can confirm this works. Gee, I looked at the manual at linux.die.net/man/1/git-stash which is out of date.man git stashis much better. -
jaf0 almost 9 yearsit's --keep-index, fwiw. -
JonnyRaa about 2 yearsthis helped me learn that 'index' == staging area
-
vhallac over 11 yearsTrue. I keep usingsavewithgit stash. Maybe it is the programmer in me insisting on honoring the symmetry with apply/pop. :) -
peterflynn about 9 yearsNote: this still stashes all your changes; the only difference from regulargit stash saveis that it leaves the already-staged changes in your working copy as well. In the workflow above this would work fine since you're just applying the stash on top of a local copy that already has half of the stash's changes (which git is smart enough to ignore). But if you edit the code before re-applying the stash, you could potentially see merge conflicts when you go to apply. Fyi. -
rjmunro about 9 years@ytpete That has bitten me so many times. I really wish there was a way for git to only stash the things you are not keeping... I often commit stuff, then do a full git stash, knowing that I cangit commit --ammendif there are problems in what I committed. -
Rhubbarb over 8 years--amend(rather than--ammend) -
Rhubbarb over 8 yearsI used the commit, stash save, amend-commit-if-necessary, stash pop method. This is fine so long as you don't amend after a push (i.e. only push after you're happy with the final amend). I'm going to try the --keep-index option on the basis that it's easy to opt to take 'upstream' or 'stashed' changes upon merge conflict. However, a properly considered resolution is probably best. As a slight aside, I find resolving conflicts to be very much easier when 3-way conflict annotations are enabled: set the "merge.conflictstyle" configuration variable to "diff3". -
Rhubbarb over 8 yearsI also prefer to explicitly specifysaveon a stash; that is helpful when you also want to provide a message string, which might otherwise be ambiguously interpreted by git. (Unlikely but possible.) -
user643011 about 6 yearsThis solution does not work for me because of the problems described by peterflynn. It is not a good answer to the question since it still stashes the staged changes. Anybody got a better solution? -
ma11hew28 over 4 yearsNote:-ualso stashes untracked files. -
jocull over 3 yearsDocs seem to say thatstash saveis deprecated now: "This option is deprecated in favour ofgit stash push. It differs from "stash push" in that it cannot take pathspecs, and any non-option arguments form the message." -
Alex over 3 yearsIt does not do what the question asked. It creates a stash that contains all modifications INCLUDING the index. What it does differently is that it does not 'resets' the index. But if you reset the index yourself and then 'stash pop', the index will be brought back. The question is about creating a stash that does NOT INCLUDE indexed files. -
Inigo over 3 yearsThis approach essentially duplicates whatgit stash save --keep-indexdoes with a lot more work. I don't see any advantages. -
Alexander Klauer about 3 years@vas No, the approach does not duplicate that. See peterflynn's comment to the accepted answer. -
Dustin Oprea about 3 yearsThis is awesome. It's a little labor-intensive, but at least you can skip and add whole files. -
Steven Lu over 2 yearsI'm a bit frustrated. I began a long cherry-pick operation last night which involves some necessary conflict management. I didn't finish, and today I collaborated with my colleagues on an unrelated section of code (since I still had the build available and running, why not). Now i've got a bunch of unstaged changes I need to save, I don't need to commit in the course of continuing a range cherry-pick, so I want to avoid that, but I cannot stash because it would slurp up the unrelated changes i've staged. Seems like I will need to commit and hope for the best. -
Steven Lu over 2 yearsFollow up, i was able to get through the situation by usinggit stash --patch -
Granfalloner over 2 yearsAs a further improvement to this snippet, its worth to add--no-verifyoption togit commit, otherwise implicit temporary commit might seriously mess up working directory because of pre-commit hook. -
whenov about 2 years@peterflynn You can usegit diffin this scenario. Usegit diff > ~/patchto export the changes between the staging area and working area,git checkoutto discard the changes in the working area, do what you need to do with the staging area, thengit apply ~/patchto restore the saved changes. -
Jmartnz over 1 yearThis is exactly what I needed thanks -
Maggyero over 1 year@whenov The problem with your approach is thatgit checkoutwon’t discard anything in the working tree aftergit reset. -
Maggyero over 1 yearExcellent, but the purpose of stashing unstaged changes was to test staged changes before committing them. So there is no point in executing your third commandgit reset --soft HEAD^. -
citysurrounded over 1 year@user643011 see my answer here: stackoverflow.com/a/71150883/5469587 -
Georgiy Bukharov over 1 yearSimple yet working! Thanks! -
citysurrounded over 1 yearNo problem! Glad I could help @GeorgiyBukharov -
VonC over 1 yearGood point. I have updated my ow answer on this page, in order to reference my other answer. -
Anthony about 1 yearBarf, sucks the feature doesn't exist -
Anentropic about 1 yearI just ran this and it stashed my unstaged changes too -
citysurrounded about 1 year@Anentropic that is exactly what OP asked for – to stash unstaged changes. Was that a typo? -
Anentropic about 1 yearI think I mis-typed, it seemed to stash everything, staged too, but tbh maybe I confused that too -
Adi H about 1 yearPro tip: You can generally combine single-character flags together:-u -mcan become-ume.g.git stash push -um "Greatest stashing ever" -
iRestMyCaseYourHonor about 1 yearI think this should be accepted answer because the one accepted does not work if you have some edits that are staged and unstaged on the same file, you getpatch does not apply. -
Lotus 12 monthsI had more luck using it as a function, not sure why but zsh choked on the above syntax:stash-working() { git commit --quiet --no-verify -m "temp for stash-working" && git stash push "$@" && git reset --quiet --soft HEAD~1; } -
Raman 12 months@Lotus Try copying it exactly as-is directly into the[alias]section of your.gitconfig. That way,zshis not involved at all. -
José Santos 11 monthsthis will stash any file that has changes that are unstaged, which means it will also stash changes that were on the staged side of those files.