Git stash
Sometimes, while working on new feature of your project you receive an urgent request to fix the critical bug or work on some other more important feature. As the changes which have been made are not commit-ready, you want to save those somewhere and get back to them later.
One naive approach would be to backup working directory, reset everything and continue work on the more urgent work. But git provides a better solution for this by providing git stash
command which temporarily stashes uncommitted changes (both staged and unstaged) off to the side of your project. By doing this git enables you to work on something else, and then come back to unfinished work and re-apply changes later on.
Stashing changes
By running git stash
git creates a stash of working directory and staging area with uncommitted changes, put them to the side and sets the state back to the point after the last commit (pointing to HEAD). At this point you’re free to make changes, create new commits, switch branches, and perform any other git operations.
The command git stash
is shorthand for git stash push
. In this mode, non-option arguments are not allowed to prevent a misspelled subcommand from making an unwanted stash entry. There are also another alias for this command git stash save
which is deprecated in favour of git stash push
.
By default git ignores untracked files when doing stash. If those files need to be added to stash you can use -u
options which tells git to include untracked files. Ignored files can be added as well if -a
option is specified. -a
will include both untracked and ignored files.
Whenever you stash changes git will create element in the stash queue and assign key and comment. The entry looks like this: stash@{#}: WIP on <branch>: <SHA1 of last commit> <last commit message>
But git provides a way to associate more meaningful message to the stash element by doing the following git stash push <message>
.
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 to git stash
, it will behave similar as the git add -p
(see more details here).
Checking what's in the stash
As git stash is a queue and contain multiple elements you would wish to see what is in there. If you run git stash list
the output can be something like this
stash@{0}: On master: typo fixed
stash@{1}: WIP on master: 82aceec commit
The output contains the following: key of the stash (stash@{#}
), followed by the comment. The comment contains information about the branch on which stash was made and the last commit that the stash was based on. The last commit is included only in the default stashing type, if you save a stash with custom message, this will not be included.
To view more details about you can use the following options:
git stash list --oneline
which will decorate stash list output with SHA1 value for each elementgit stash show <SHA1>
which will show a quick summary of the changes madegit stash show -p <SHA1>
which will show the patch-style differences of the changes made (full diff)
Re-applying changes
To reapply the stashed changes there are two options for doing this: apply and pop. Each of this options will apply the stashed changes into staging area as well to working directory. These options can be used on any branch, not just the branch where the stash was saved originally.
Apply option will update your environment with the changes, but will keep the element in the stash queue. On contrary pop option will remove the element from the stash queue. The apply option is useful if you want to apply stash across multiple branches. The pop option removes element from the head of queue.
The basic command syntax for reapplying stash has the following form:
git stash apply
git stash pop
but you can also specify the element which you wish to apply/pop by adding key of the element as the last argument of the command, for example
git stash apply stash@{4}
git stash pop stash@{4}
Sometimes there can be conflicts when apply/pop are executed. This happens because the current branch state diverges from the changes in the stash. You can resolve this in two ways:
- resolve conflict manually
- create new branch out of the stash
You can use git stash branch
to create a new branch to apply your stashed changes to. This checks out a new branch based on the commit that you created your stash from, and then pops your stashed changes onto it.
git stash branch awsome-feature stash@{3}
Cleaning up
The stash list can be contain clutter which you forgot to remove, or you just want to discard in-progress changes as the scope changed. To clean up unnecessary entries you can use:
git stash drop stash@{#}
which will remove specific elementgit stash clear
which will remove all elements from the stash queue