Stashing only un-staged changes in Git

I'd like to do the following work flow:

  1. Add changes to the stage.
  2. Stash all the other changes that were not staged.
  3. Do some stuff with the things in stage (i.e. build, run tests, etc)
  4. Apply the stash.

Is there a way to do step 2?

Example

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123

git stash push has an option --keep-index that does exactly what you need.

So, run git stash push --keep-index.


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.


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


With git version 2.7.4 you may do:

git stash save --patch

The git will ask you to add or not your changes into stash.
And you then just answer y or n

You can restore working directory as you always do that:

git stash pop

or, if you want to keep saved changes in stash:

git stash apply

Stashing just the working tree (unstaged changes) in Git is more difficult than it should be. The accepted answer stashes the unstaged changes, but also stashes the staged changes (and leaves them staged as well), which is rarely what you want.

This alias works well:

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.