Git Stash – How To Save Uncommitted Changes In Git

Introduction

Stashing is a feature in Git that allows you to save your uncommitted changes. Think of it like a temporary area in git where your work will be saved and later you can pick that work and create commits. Stashing works only for local and does not apply to remote repositories like Github, Bitbucket, Gitlab, etc.

Let’s assume a scenario where you are working on some changes in a feature branch and suddenly your teammate asks you to take care of his/her work on priority. Your work in the feature branch cannot be committed at this moment since the work is not fully completed. In this case, if you try to switch branches, two things will happen.

  • Uncommitted files from your branch will follow you unless you commit them.
  • If there is any conflict between two branches git will not allow you to switch branches unless you commit the changes.

Sample Project – Git Stash

I will create a sample project and demonstrate both of the above scenarios.

STEP 1 – Initialize new git repository. I have created the project directory under /tmp/ but you can create it in any location as you wish.

$ mkdir /tmp/git_stash_tmp
$ cd /tmp/git_stash_tmp
$ git init
Initialized empty Git repository in /tmp/git_stash_tmp/.git/

STEP 2 – Add two commits to the main/master branch.

$ echo '## Random commit 1 for stash ##' >> file_stash.txt
$ git add .
$ git commit -m 'Commit 1 done for file_stash.txt'

$ echo '## Random commit 2 for stash ##' >> file_stash.txt
$ git add .
$ git commit -m 'Commit 2 done for file_stash.txt'

STEP 3 – Create a feature branch.

$ git checkout -b feature
or
$ git switch -c feature

Add new content to the file_stash.txt file.

$ echo '## commit 1 for stash in feature branch ##' >> file_stash.txt

Scenario 1 – Uncommitted Files Will Be Followed To Other Branches

I have two branches main and feature where I made a couple of commits in the main branch as shown in the last section. Now I am working on the feature branch having uncommitted changes.

$ git status  
On branch feature
Changes not staged for commit:
 (use "git add <file>..." to update what will be committed)
 (use "git restore <file>..." to discard changes in working directory)
       modified:   file_stash.txt
no changes added to commit (use "git add" and/or "git commit -a")

If I try to switch branch, the uncommitted change will be followed to other branches.

$ git switch main
M       file_stash.txt
Switched to branch 'main'

You can run the git status command and see the file modified in the main branch.

$ git status
On branch main
Changes not staged for commit:
 (use "git add <file>..." to update what will be committed)
 (use "git restore <file>..." to discard changes in working directory)
       modified:   file_stash.txt
no changes added to commit (use "git add" and/or "git commit -a")

Scenario 2 – Conflict When Switching Branch

If there are changes made to the same set of files in both branches then git will not allow you to switch branches due to conflict.

Here I made one more commit to the main branch.

# Main Branch
$ echo '## Random commit 3 for stash ##' >> file_stash.txt
$ git commit -a -m 'Commit 3 done for file_stash.txt'

Let me make some changes to the file under the feature branch but changes are not committed.

# Feature Branch
$ echo '# Random commit under feature branch ##' >> file_stash.txt
$ git status -s
M file_stash.txt

Now the main and feature branches have diverged. When I try to switch to the main branch without committing it will abort the operation with the following error.

$ git switch main
error: Your local changes to the following files would be overwritten by checkout:
       file_stash.txt
Please commit your changes or stash them before you switch branches.
Aborting

In this case, you have to use stashing to switch branches.

Git Stash – Man Page & Help

The git stash command has a man page and a helper option to display the supported flags.

To access the git stash man page run the following command.

$ man git-stash
or
$ git-stash --help

To access the helper section of git stash run the following command.

$ git stash -h

Stash Uncommitted Work In Git

As foretold in the introduction, the stash is like saving your work for later use. You can stash only the uncommitted changes i.e. modified objects in the working directory and staged objects.

All you have to do is run the git stash command and your work is saved.

$ git stash
Saved working directory and index state WIP on feature: f551753 Commit 2 done for file_stash.txt

If you see the output of the git stash command it says, saved working directory and index which is nothing but the staging index. If you run the git status command you will not see any changes you made.

$ git status
On branch feature
nothing to commit, working tree clean

Now you can switch between branches without worrying about your unsaved work.

NOTE: It is possible to create multiple stash copies in Git. Every time when you run the git stash command the changes will be saved in new stash reference stash@{*}

Stash Untracked & Ignored Files Git

By default, the stash command will not stash untracked and ignored files.

To stash only the untracked files you can use the -u or --include-untracked flag along with the git stash command.

$ git stash -u
or
$ git stash --include-untracked

To stash all the files irrelevant to their state(Untracked, ignored, working copy, staged) run the git stash command with the -a or --all flag.

$ git stash -a
or
$ git stash --all

View Git Stash List

To view the stashed list run the git stash list command.

$ git stash list
stash@{0}: WIP on feature: f551753 Commit 2 done for file_stash.txt
stash@{1}: WIP on feature: f551753 Commit 2 done for file_stash.txt

Let’s understand the output in detail.

  • stash@{} ⇒ This is the reference to the stashed changes. The last stash will be referred to with stash@{0} and the subsequent stash reference numbers will be referred to with 1,2,3..N.
  • WIP on feature ⇒ Points to the branch name at which the copies are saved.
  • f551753 Commit 2 done for file_stash.txt ⇒ This is an auto-generated stash message when you run the git stash command. If you look at the last output, the message is the same for both stashes. When working with multiple stashes this will create confusion. The recommended approach is to create a custom message when creating a stash.

Git Stash With Custom Message

To save the stash with a custom message run the git stash save command. We will make one more change to the file_stash.txt file and stash it.

$ echo “Adding some API feature” >> file_stash.txt
$ git stash save "JIRA123 - WIP - Add new API feature"
Saved working directory and index state On feature: JIRA123 - WIP - Add new API feature

Run the git stash list command. As you can see the stash@{0} is added with a custom message.

$ git stash list
stash@{0}: On feature: JIRA123 - WIP - Add new API feature
stash@{1}: WIP on feature: f551753 Commit 2 done for file_stash.txt
stash@{2}: WIP on feature: f551753 Commit 2 done for file_stash.txt

Git Stash Diff

The stash show option will display the diff between the given stash content and the commit when the stash entry was created.

$ git stash show stash@{0}
file_stash.txt | 1 +
1 file changed, 1 insertion(+)

For more detailed diff info you can pass the -p or --patched flag.

$ git stash show -p stash@{0}
diff --git a/file_stash.txt b/file_stash.txt
index ab98a9c..0925c2a 100644
--- a/file_stash.txt
+++ b/file_stash.txt
@@ -1,2 +1,3 @@
## Random commit 1 for stash ##
## Random commit 2 for stash ##
+Adding some API feature

Git Stash Apply & Pop

To start working with the stashed copy you can either use the git stash apply or git stash pop command. Both commands use the Last In First Out(LIFO) approach and restore the stash@{0} copy. The git stash apply command will restore the last stashed change(stash@{0}) to the working copy. You can also give the stash reference which will restore the particular reference instead of the last stash.

$ git stash apply
or
$ git stash apply stash@{1}
On branch feature
Changes not staged for commit:
 (use "git add <file>..." to update what will be committed)
 (use "git restore <file>..." to discard changes in working directory)
       modified:   file_stash.txt
no changes added to commit (use "git add" and/or "git commit -a")

NOTE: The apply command just restores the changes from the stashed copy but will not completely remove the stashed copy.

The git stash pop command is the same as the apply command but it will restore the changes to the previous state and remote the stashed copy.

$ git stash pop
or
$ git stash pop stash@{1}

Create A New Branch And Apply Changes

You might have created commits after stashing. When you try to apply the stash back to the working copy it will result in conflict. So it is best to create a separate branch using the git stash branch command.

$ git stash branch <branchname> <stash ref>
$ git stash branch stash_reset stash@{0}

The above command will restore the stashed changes to the given branch and remove them from the stash completely.

Delete Stash In Git

You can use the git stash drop command to delete one or more stashes using the reference ID.

$ git stash drop stash@{1}
Dropped stash@{1} (29b45bdabd0a4e584872eceb3499da655893d4a4)

You can also delete all the stashes using the git stash clear.

$ git stash clear

Summary Of Commands

This section contains the list of git stash commands used in this guide.

COMMANDUSAGE
git stashSave the working copy along with staged changes
git stash save “message”Stash untracked files too
git stash listList the stashed copy
git stash --include-untrackedThe short syntax for –include-untracked
git stash -uThe short syntax for –all
git stash --allStash all changes including working copy, staging, untracked, ignored file
git stash -aSame as the last command but shows detailed output
git stash show stash@{0}Show diff between the saved stash content and the last commit
git stash show -p stash@{0}Same as last command but shows detailed output
git stash applyAdd the stashed content back to the previous state. The copy of the stash is not removed
git stash popAdd the stashed content back to the previous state. The copy of the stash removed
git stash drop stash@{1}Remove one or more stash
git stash clearRemove all stash

Wrap Up

In this article, we have seen what is git stash and how to stash the uncommitted changes. If you have any feedback with respect to this article please share it through the comment section.

Leave a Reply

nineteen + 18 =