Stashing

Stashing is a pretty simple concept that is incredibly useful and very easy to use. If you are working on your code and you need to switch to another branch for some reason and don't want to commit your current state because it is only partially completed, you can run git stash, which will basically take the changes from your last commit to the current state of your working directory and store it temporarily.

In the following example, I have a change to my 'lib/simplegit.rb' file, but it's not complete.

$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#       modified:   lib/simplegit.rb
#
no changes added to commit (use "git add" and/or "git commit -a")

$ git stash
Saved working directory and index state "WIP on master: c110d7f... made the ls-tree function recursive and list trees"
(To restore them type "git stash apply")
HEAD is now at c110d7f made the ls-tree function recursive and list trees

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

Now I can see that my working directory is clean, as if I had committed, but I did not. Now I can switch branches, work for a while somewhere else, then switch back. So where did that change go? How do I get it back? Well, I can see my stashes by running git stash list.

$ git stash list
stash@{0}: WIP on experiment: 89e6d12... trying git archive
stash@{1}: WIP on master: c110d7f... made the ls-tree function recursive
stash@{2}: WIP on master: c110d7f... made the ls-tree function recursive

I see I have two stashes on the 'master' branch, both saved off of working from the same commit, and I have one stashed change off the 'experiment' branch. However, I can't remember which stash was the one I want, so I can use git stash show to figure it out.

$ git stash show stash@{1}
 lib/simplegit.rb |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

$ git stash show stash@{2}
 lib/simplegit.rb |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

I can also use any normal git tools that will take a tree on it, for instance, git diff:

$ git diff stash@{1}
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index e939f77..b03bc9c 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -21,10 +21,6 @@ class SimpleGit
    command("git ls-tree -r -t #{treeish}")
  end

-  def commit(message = 'commit message')
-    command("git commit -m #{message}")
-  end
-
  private

    def command(git_cmd)

And finally, I can apply it:

$ git stash apply stash@{1}
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#       modified:   lib/simplegit.rb
#
no changes added to commit (use "git add" and/or "git commit -a")

Now we can see that our working directory is back to where it was, with one file in an unstaged state. Now I would have to git add and git commit it if I wanted to keep the change.

Normally it's not even this complicated. If you run git stash apply without the actual stash reference, it will just apply the last stash you saved on that branch. Normally I will just use git stash to save something, go work elsewhere, then come back and run git stash apply to get back to where I was.