Git is a distributed version control system developed by Linus Torvalds. It has become the standard in software development due to its efficiency and flexibility.
During the development process, there are situations when you need to urgently switch to another branch using the checkout command and make changes related to a different task. However, the current changes may not be ready for a commit yet, and you don’t want to lose them. In such situations, the git stash
command comes to the rescue. This tool is indispensable, allowing you to safely store current changes for a while and then return to them without disrupting the integrity of the repository.
Let’s explore how to use git stash
in development.
Let's think about how we normally work with the codebase and Git. We create something (a function or a small module), then run git add
, followed by git commit
and git push
. Great; we have finished the task and can move on to the next one.
But what if the context changes, and you need to switch urgently?
You may not have finished writing the module yet, but you must complete another task now. You don’t want to leave the commit unfinished. This is where git stash
comes in. So, what does it do?
The process of saving temporary changes consists of two stages:
stash
: We save the changes to a special storage. You can also add a comment for them.pop
or apply
: We bring the changes back into our working directory.The version control system must track changes you are going to stash. You can add files to the tracked list using the command:
git add .
To create a stash, use the following command:
git stash
Output:
Saved working directory and index state WIP on master: 099797d start
By default, the stash name contains the abbreviation “WIP” (Work In Progress) and the branch name. If you want to specify a comment, you can use the following commands: git stash push
or git stash save
:
git stash push -m "<your comment>"
The result will be:
Saved working directory and index state On master: <your comment>
The same result will occur with this command:
git stash save "<your comment>"
However, this command is considered deprecated — you can check the documentation for more details.
Now, let’s return to the original task. We need to bring back the hidden changes. Use the command:
git stash pop
The output will tell you that the changes have been applied to the current working area and can now be used. It will also indicate that all data has been removed from the special temporary storage.
If you need to apply the changes without removing them from the stash, use the command:
git stash apply
To view the list of changes that have been stashed in the repository, you can use the command:
git stash list
Example output:
stash@{0}: On master: User Story #2010
stash@{1}: WIP on master: 099797d start
To apply a specific change, you can use the pop
command with the stash index:
git stash pop 'stash@{1}'
Example output:
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{1} (563f9c20ab12525795911fbed0c4ebf4a1298b4e)
If you need to stash changes while keeping them in the working directory, use the --keep-index
flag. In this case, files added to the tracked list using the git add
command will remain:
git stash --keep-index
Output:
Saved working directory and index state WIP on master: 099797d start
If you call git status
after this, the modified files will still be there:
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: GitStash/Program.cs
modified: GitStash/SomeModule.cs
If you need to add files that git does not track yet, use the --include-untracked
flag:
git stash --include-untracked
When you retrieve changes using pop
, you will see a message about the presence of untracked files:
...
Untracked files:
(use "git add <file>..." to include in what will be committed)
GitStash/NewClass.cs
...
Sometimes it may be convenient to split the uncommitted changes into separate stashes. In this case, the git stash -p
command will help:
git stash -p
For each change, hiding will be done separately, with a prompt for confirmation. Here are the options for confirmation:
The show
command displays information about the changes in a specific stash, for example:
git stash show
GitStash/Program.cs | 3 ++-
GitStash/SomeModule.cs | 7 +++++-
2 files changed, 8 insertions(+), 2 deletions(-)
You can also specify the index of a specific stash:
git stash show 'stash@{1}'
Example output:
GitStash/SomeModule.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
To remove a specific stash, you can use the drop command. If you don't specify an index, it will remove the most recent set of stashed changes:
git stash drop
Or:
git stash drop 'stash@{1}'
Output:
Dropped stash@{1} (bedb3c2add59a3f203e2367602328dca8b33b6e9)
To completely clear the stash storage, you can use the command:
git stash clear
To create a new branch based on stashed changes, use the following command:
git stash branch <branch name> <stash index>
Or simply:
git stash branch <branch name>
For example:
git stash branch some-feature stash@{2}
The set of changes we hide in the stash is actually a series of commits. Running this command creates two or three commits:
stash@{0}
contains the stashed files.HEAD
commit in Git's current working directory.--keep-untracked
flag, a separate commit will be created for the untracked files.What happens when you run the pop
command?
The .git/refs/stash
file contains a reference to the last commit for the stash.
cat .\.git\refs\stash
Output:
07ea0c456356e883610f43c20d9cb298ff2ebb8a
Let's look at some common use cases for this mechanism in practice:
The merge
/ rebase
commands are necessary when working with multiple branches. However, conflicts often arise that can cause important changes in the current working directory to be lost.
Before performing a merge, ensure that the current branch is up to date, i.e., it doesn't contain unsaved changes. If you have unsaved changes that should be preserved before merging, run this command:
git stash push -m "Backup before branch merge"
Proceed with the merge, running merge
or rebase
.
Conflicts may arise between the changes in the current branch and the changes in the other branch when executing these commands. You can resolve conflicts using either IDE tools or Git.
After successfully completing the merge or rebase, you can restore the changes to the current working directory using apply
or pop
.
The stash mechanism can also be helpful for working with non-debugging changes, such as temporary fixes, comments, or code formatting. Instead of committing these changes to the current commit, you can use git stash
to save them temporarily. This helps in creating clean commits and improves the structure of the Git history.
Another scenario for using git stash
is effectively managing project configurations. Depending on the task or environment you are working in, you might need to modify configuration files, but permanently saving them might not be practical.
Saving different configurations
Suppose there is a configuration file that defines the parameters for your application (e.g., config.json
). You need several versions of this file for different use cases (e.g., local development, testing, and production). You can use the stash to save these configurations.
# Saving the configuration for local development
git stash save "Local configuration"
# Saving the configuration for testing
git stash save "Testing configuration"
# Saving the configuration for the production environment
git stash save "Production configuration"
Applying configurations as needed
When you need to switch between different configurations, simply use git stash apply
or git stash pop
to apply the corresponding stash:
# Applying the configuration for testing
git stash apply stash@{1}
WIP on master: 099797d start
Use the push
or save
commands to add descriptive messages, for example:
git stash save "test configuration"
Or:
git stash push -m "Started working on issue #11 - added contract for the module"
list
and show
commands to view the changes and git stash drop
to remove obsolete stashes. This mechanism is not intended for long-term data or change storage.git stash
with other commands, such as git stash branch
, to create new branches, or with the rebase
and merge
commands to back up local changes.In this article, we’ve explored the git stash
command and its use cases. git stash
is a powerful tool that can significantly simplify managing changes in your repository and improve your workflow. We’ve examined both basic and advanced scenarios for using this tool, including creating, applying, extracting, and managing stash entries.