Git Stash - Save changes for later

Git

In this tutorial we will learn to stash changes in Git.

git stash

We use the git stash command when we want to save and not commit the changes we have made in our working directory and return back to it later.

Example: Lets say you are adding a new feature. And then an urgent need to fix a bug rises. You are not yet ready with the new feature and you have not committed it in your Git repository. So, in this case you can stash the changes and return back to the last committed state of the working directory and fix the bug. Once done you can get back the "new feature" changes from the stash and resume working on it.

Stash is local

When we execute the git stash command we are stashing the changes in our local repository and the stashes are never moved to the repository server.

Following is the status of the git-project we created in the Setting up Git repository tutorial.

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

And following are the files in the repository.

$ ls -la
total 0
drwxr-xr-x   5 yusufshakeel  staff  170 Feb 12 19:46 .
drwxr-xr-x  28 yusufshakeel  staff  952 Feb 14 22:42 ..
drwxr-xr-x  14 yusufshakeel  staff  476 Feb 16 19:00 .git
-rw-r--r--   1 yusufshakeel  staff    0 Feb 12 19:26 index.php
drwxr-xr-x   3 yusufshakeel  staff  102 Feb 12 19:46 js

Lets make some changes to the index.php file and check the status of the working directory using git status command.

$ git status
On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   index.php

no changes added to commit (use "git add" and/or "git commit -a")

Now, lets say we want to revert back to the inital state of the working directory and we don't want to lose the changes done to the index.php file.

In this case we will stash the changes using the git stash command.

$ git stash
Saved working directory and index state WIP on master: f066f07 initial commit
HEAD is now at f066f07 initial commit

Now all the changes are stashed and we are back to the last commit.

In the above output we see the message ...WIP on master: f066f07 initial commit... which means the changes are stashed on master branch and from the last commit f066f07.

By default, stash are marked as WIP - "Work In Progress" on top of the branch and commit from which we created the stash.

If we now execute the git status command we will get the following.

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

Stash with a message

To create a stash with a message we use the git stash save "message" command where, "message" is what we want to set for the stash.

$ git stash save "new feature"

Default behaviour of git stash

By default, the git stash command will stash files that are being tracked i.e., already added to the Git repository or are staged i.e., ready for commit.

Files that are ignored (Git Ignore) and files that are newly created and not yet staged are not stashed by git stash command by default.

Stash untracked files

To stash untracked files we use the git stash -u command.

Lets say we create a new file README inside the project folder and check the status of the repository using git status command.

$ git status
On branch master
Untracked files:
  (use "git add ..." to include in what will be committed)

	README

nothing added to commit but untracked files present (use "git add" to track)

If we use git stash command then the new file README will not get stashed as it is untracked and not committed in Git repository.

$ git stash
No local changes to save

To stash the new file we have to use the -u option.

$ git stash -u
Saved working directory and index state WIP on master: f066f07 initial commit
HEAD is now at f066f07 initial commit

Stash all

To stash all the files (tracked, staged, new files, ignored files) we use the git stash -a command.

List stash

To list the stash we use the git stash list command.

$ git stash list
stash@{0}: WIP on master: f066f07 initial commit
stash@{1}: WIP on master: f066f07 initial commit

In the above output we see two stashes and they are marked as stash@{0} and stash@{1}.

Pop a stash

If we want to re-apply the most recently created stash we use the git stash pop command.

$ git stash pop
Already up-to-date!
On branch master
Untracked files:
  (use "git add ..." to include in what will be committed)

	README

nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (af18d2ac781301c4f9a6cd14f21be74083dd0129)

In the above output we can see that the README file that was stashed is now re-applied to the working directory. And the last line Dropped refs/stash@{0} say that stash stash@{0} is removed from the stash list.

Re-apply a specific stash

To re-apply a specific stash we use the git stash pop stash@{id} command.

$ git stash pop stash@{0}

Delete specific stash

To delete a specific stash we use the git stash drop stash@{id} command.

$ git stash save "new feature"
Saved working directory and index state On master: new feature
HEAD is now at f066f07 initial commit

$ git stash list
stash@{0}: On master: new feature

$ git stash drop stash@{0}
Dropped stash@{0} (d1b5d4fbabaf246d8436dd038fdca23cc9a90a29)

Delete all stashes

To delete all stashes we use the following command.

$ git stash clear