How to : git stash

Stashing is a great way to pause what you’re currently working on and come back to it later. Suppose you are working on something, and suddenly, something high priority comes up, like a production bug. Ah, lets see.. a storyboard can make things light..

So, wonderful morning, and you wanted to do some performance improvements to the code..

So, you create a new branch and make the changes, and you see that the changes are seen when you run a git status

$ git checkout -b performance
Switched to a new branch 'performance'

vi JobPersist.java

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

But, I am not done and not ready to commit the data. Then, something important comes up. You don’t have time to complete your work and will have do something else.

So, to get the latest code, you do a pull, and see what happens.

$ git pull
remote: Counting objects: 51, done.
remote: Compressing objects: 100% (34/34), done.
remote: Total 51 (delta 15), reused 37 (delta 9)
Unpacking objects: 100% (51/51), done.
From https://github.com/nikhilkuria/jobRunner
f175a2b..987a41f master -> origin/master
* [new branch] performance -> origin/performance
Updating f175a2b..987a41f
error: Your local changes to the following files would be overwritten by merge:
jobRunner/src/com/job/persist/JobPersist.java
Please, commit your changes or stash them before you can merge.
Aborting

So, git tells me to either commit or stash. Since, I am not ready to commit, I just shove all the work away under the sheet and resume working when I am done with the new work. Stashing is the best way to do this.

The stash command in Git is kind of like a clipboard; you can stash away any changes in your current branch to work on something else for a while. You can change branches and perform other commits.

$ git stash
Saved working directory and index state WIP on master: f175a2b Adding relationsh
ips
HEAD is now at f175a2b Adding relationships

So, now the branch moved back to the previous commit and moved all my tracked files to a ‘stash’, making the working directory clean

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

I can also see the list of all my stashes,

$ git stash list
stash@{0}: WIP on master: f175a2b Adding relationships

So, and finally, you are done with the new job and is ready to continue working on the performance issue. You can bring back the stash using the command, git stash apply

$ git stash apply
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: JobPersist.java
#
no changes added to commit (use "git add" and/or "git commit -a")

So, this brought back my previous work and I can complete this at peace.

There are cases when you can have multiple stashes,

$ git stash list
stash@{0}: WIP on master: eec8b6f fix for prod issue
stash@{1}: WIP on master: ba8de07 initial commit

So, if you need to go back to a specific stash, you could pass the stash id as a param to git stash apply

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

The changes to your files were reapplied, but the file you staged before wasn’t restaged. To do that, you must run the git stash apply command with a --index option to tell the command to try to reapply the staged changes. If you had run that instead, you’d have gotten back to your original position:

$ git stash apply stash@{4} --index
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: JobPersist.java

You could also resume your work by creating a new branch from stash. (highly recommended). Running
git stash branch <branchname> [<stash>]
which creates a new branch for you, checks out the commit you were on when you stashed your work, reapplies your work there.

$ git stash branch performance-new stash@{4}
Switched to a new branch 'performance-new'
# On branch performance-new
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: JobPersist.java
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{4} (448b5faf608729000757f65a8d309a8e3fc3aa8d)

You could read further here and here.