Manage uncommitted changes with Git Stash
These are 2 common situations we run into as software developers using Git.
- You're working on a feature branch and suddenly need to switch to another branch to fix a bug.
- You want to update your local branch with the latest changes from the remote repository.
In both cases you often have uncommitted changes that need to be stored somewhere. Making a temporary commit would work. Another way to store these changes is by using Git stash. Running git stash
will save the changes and to retrieve them later we can use git stash pop
.
Stashes are stored in a stack which means that the last item added, will be the first item that comes out.
That is if we only rely on the push (git stash push
or the short form git stash
) and pop (git stash pop
) methods. While this works fine for a lot of use cases, it has the potential to become problematic when there are multiple items in the stack and we want to retrieve an item that isn't the most recent one.
Fortunately, Git stash provides a way to efficiently handle multiple stashes. In this article I will show the commands and flags that I regularly use and hopefully help improve your Git workflow when working with stashes.
Naming stashes
It is easy to lose track of the changes when there are multiple stashes. Fortunately it is possible to add a message when creating a new stash. For that we can add the -m
flag with a message. For example:
$ git stash -m 'refactor payment'
$ git stash list
stash@{0}: On main: refactor payment
stash@{1}: WIP on main: 89da19c Update meta description
Instead of WIP
and the last commit message, it now shows the stash with our custom message. Which makes it much easier to identify when we want to start working on the stashed changes again. This is why I make it a habit to always attach a message whenever I stash some work. Even when I'm pretty sure I will very soon continue working on the stashed changes.
Untracked files
One cause of confusion for a lot of people (Including me in the past), is that untracked files are not included in the stash by default. So when new files have been created and we run git stash
, these files will not be included in the stash and still be available in the working directory.
To make sure that new/untracked files are included in the stash we can use the --include-untracked
or -u
flag. This will add all untracked files to the stash. For example:
$ git stash --include-untracked
See what has been stashed
To see everything that has been stashed, the git stash list
command can be used. This will show a list of all stashes with the last stash at top and the oldest at the bottom.
All stashes will have the following name format:
stash@{<index>}: WIP on <branch>: <latest commit hash> Commit message
For example
$ git stash list
stash@{0}: WIP on develop: 5a22ab2 Add content
stash@{1}: WIP on main: 89da19c Update meta description
stash@{2}: WIP on main: 89da19c Update meta description
The default stash name only tells us the branch and the last commit at the time of the stash, but nothing about the changes that we have stashed. We can view the changes in a specific stash by using the following command: git stash show -p <index>
. Where <index>
is the number shown between the curly braces stash@{2}
. By adding the -p
or --patch
flag, it will show the actual code changes in the output, instead of just the filenames with the number of changes.
I regularly use this when there are multiple stashes and I want to see what changes a specific stash contains. Or if I have old stashes for which I don't remember what they contain.
Retrieving a specific stash
The changes from a specific stash can be retrieved with the git stash apply
command. This will apply the changes from the stash to the working directory, but will keep the stash in the stack. When called like this without any additional arguments, it will apply the most recent stash. To apply a specific stash we can use the git stash apply <index>
command. In older versions of Git (pre 2.11) instead of just the index, the full stash name had to be used. For example git stash apply stash@{2}
.
For example:
$ git stash list
stash@{0}: WIP on develop: 5a22ab2 Add content
stash@{1}: WIP on main: 89da19c Update meta description
# Apply the most recent stash
$ git stash apply
# Apply the stash at index 1
$ git stash apply 1
Of course it's also possible to use the git stash pop
command to apply the changes. This would also immediately remove the stash from the stack. This is the same as running git stash apply
followed by git stash drop
.
Deleting stashes from the list
After applying the stash with git stash apply
the stash will still be kept in the stack. This means that after a while the list of stashes can become quite long, which makes it harder to keep track of what is in each stash.
To remove a single stash we can use the git stash drop <index>
command. Where <index>
is the number shown between the curly braces, such as stash@{2}
.
To remove all stashes from the stack at once we can use the git stash clear
command. Be cautious with this command as it will remove all stashes and there is no way to get them back. This is probably also the reason why I seldom it.
$ git stash list
stash@{0}: WIP on develop: 5a22ab2 Add content
stash@{1}: WIP on main: 89da19c Update meta description
stash@{2}: WIP on main: 89da19c Update meta description
# Remove the stash at index 1 (stash@{1})
$ git stash drop 1
# Remove all stashes
$ git stash clear
Conclusion
Git stash is a very useful tool to temporary store uncommitted changes when we need to switch branches or pull changes from remote. By making use of commands other than just git stash
and git stash pop
, working with stored changes becomes much more convenient.
Hopefully this article has shown you some new commands and flags to make working with Git stash easier and helps you improve your overall Git workflow.