Git Stash: A Detailed Guide to Shelving Your Code

9 min read

We’ve all been there. You’re heads-down on an important feature when your Slack notifications suddenly start pinging. Someone on your team needs a hand troubleshooting a critical bug. You want to help them try to reproduce the bug, but your changes aren’t ready to commit. You need to switch to the release branch, but you don’t want to permanently include your changes on your current feature branch.

Fortunately, there’s a tool for that. Git calls this tool “stash,” and it lets you take your current changes and magically zip them away from view. They aren’t lost. In fact, Git saves them for you on your local computer for as long as you keep the repository on that hard drive. But it does remove them from the current branch and return it to the state it was in the last time you committed.

What Is

As we mentioned, git stash is a tool that removes the working changes from your current branch and saves them as a diff. Later, you can apply those changes from a list of stashed changes—either on your current branch or on a different branch after you switch branches.

One nice feature of git stash is that applying the changes doesn’t remove them from the list of stashed states. So, if you’re working on a patch for a particular bug, you could stash changes, then try to apply them to multiple feature branches to make sure that your fix works. This beats merging your branch into those branches. Merging modifies the history of the branch you’d be working on. While that’s OK if you’re the primary person working on that branch, if you’re helping to patch a bug for some teammates you might not want to commit your changes to their branches, too. There are lots of good reasons to try to limit the size of a branch’s changeset.

You can use git stash to apply your changes to those other branches without committing them. You can test out your changes in those branches to see if they fix the bug before committing them to your own branch. Then, when it comes time to open a pull request, you’ll be certain that your changes work, but you’ll also be certain that your pull request—as well as theirs—only contains the changes that it really needs.

How Does

There are a few different ways you can use the git stash command to save your work without committing it. Let’s dive into some of the most common variations of the command to see how they work and how you can use them.

git stash 

Let’s start simple. You have a big list of tracked changes on a branch. You run the most basic stash command, git stash. Boom! Your changes are stashed away and kept as a diff inside a special portion of your Git repository. 

Let’s use an example repository to show just how this works. I have a repository that has some files added by my IDE. I’ve staged them all, so my git status looks like this:

Changes to be committed:

 (use "git restore --staged <file>..." to unstage)

       modified:   .idea/ExampleRepo.iml

       new file:   .idea/compiler.xml

       modified:   .idea/misc.xml

       new file:   .idea/modules.xml

       new file:   .idea/vcs.xml

       modified:   .idea/workspace.xml

Now, let’s run git stash.

➜  ExampleRepo git:(master) ✗ git stash

Saved working directory and index state WIP on master: 60ab63f Initial commit

Then, when we check our git status again, we’ll see that there’s nothing in our working tree.

➜  ExampleRepo git:(master) git status

On branch master

Your branch is up to date with 'origin/master'.

 

nothing to commit, working tree clean

Git went through and cleaned up our changes. The branch is now completely clean.

git stash list

You’ve stashed some changes. Maybe you did it more than once. When that’s the case, you need to be able to figure out which of your changes you’ve socked away. That’s where the list parameter to the stash command comes in. Let’s look at it with an example to see how it works.

This is the same repository we were working with earlier. As you saw, our working tree is clean. Let’s run the command:

➜  ExampleRepo git:(master) git stash list

Unlike before, this will open an interactive list instead of just printing out our changes. The list of stashed changes will take control of your terminal and look something like this:

stash@{0}: WIP on master: 60ab63f Initial commit

(END)

Git gives us a list of stashed change sets. If you have stashed many changes, (END) will instead appear as (more). Use the space bar to page through the list of changesets. To stop viewing changesets, press the q button.

git stash apply

So, let’s say that you want to actually apply one of those changesets. For that, you use the apply parameter. Let’s see it in action.

➜  ExampleRepo git:(master) git status

On branch master

Your branch is up to date with 'origin/master'.

 

nothing to commit, working tree clean

Again, our working tree is clean. Let’s see what happens when we use the command git stash apply.

➜  ExampleRepo git:(master) git stash apply

On branch master

Your branch is up to date with 'origin/master'.

 

Changes to be committed:

 (use "git restore --staged <file>..." to unstage)

       new file:   .idea/compiler.xml

       new file:   .idea/modules.xml

       new file:   .idea/vcs.xml

 

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:   .idea/ExampleRepo.iml

       modified:   .idea/misc.xml

       modified:   .idea/workspace.xml

Git has restored your changes, but not in the exact working state you were in before they were stashed. If you’re ready to commit the changes now, use git add or git commit -a to stage and commit the changes to your branch.

As we previously mentioned, apply doesn’t remove the list of changes from your stashed change list. Run git stash list again and you’ll see that your previous set of changes still exists.

git stash pop

So, what do you do if you want to apply a set of stashed changes but don’t want to keep them around later? That’s where the pop parameter to git stash comes in. Pop-ing some changes does the exact same thing as apply, but it doesn’t keep the changes in your list of changes.

Sometimes, pop is the right tool to use for what you’re doing. Sometimes, apply is the right tool. It’s up to you and whether you think you’ll need to reuse those changes in another context. If you keep some changes around and later realize you don’t need them, you can always delete them from the list later.

Advanced Usage

If you’ve been using git stash for a little bit and you want to take your usage to the next level, check out some advanced parameters to git stash

Untracked Changes:

When we talked about stashing changes before, you might’ve noticed that when we stashed them, the command only stashed tracked changes. The difference between tracked and untracked changes can be a little confusing. The gist is that tracked files are files that were in the project as part of your last commit.

By default, Git doesn’t always know what to do with brand-new files when you’re stashing them. Also, it can be surprising to stash files and see brand-new files disappear from your hard drive. So, Git requires that you tell it you want to stage untracked files before you do.

Create a Branch From Stashed Changes:

I’ll admit, this is a common use case for me. I’m getting started on some new feature, and I begin tinkering with some code to start working on my changes. It isn’t until a while later that I realize: I’m still modifying the master branch. Whoops!

So, I’ll stash my changes, then use the git stash branch command. This creates a new branch based off the working branch and automatically applies my changes. You should note: When you successfully apply your changes to the new branch, Git will delete the stashed changes.

Choose Your Change Set:

Sometimes you want to stash certain changes but completely discard others. Maybe you’ve been working on a fix for a bug, but you’ve also littered the code with debugging statements. In that case, you’d want to stash the changes related to the bug fix but send the debugging statements into the ether.

That’s where the --patch parameter comes in. When you start to stash changes with this parameter, instead of blindly stashing all changes, it’ll open an interactive terminal and present you with changes one at a time. You’ll choose whether to keep or discard the chunk of code it presents, one by one. Changes you keep will be stashed; changes you discard will not be stashed.

This might sound a little daunting at first, but it’s actually quite simple once you’ve had a chance to work with it. It doesn’t translate very well to static text, but I recommend giving it a try. You’ll find it’s really simple once you’ve done it once or twice.

Don’t Be Afraid of

Learning the Git command line is often intimidating. Git is an enormous program. It’s not particularly discoverable, either. But one of the great things about git stash is that, by default, everything you do is reversible. Stashing your changes provides a lot of flexibility for switching between different code branches without committing them.

If you’re interested in learning more about the git stash command, I recommend this terrific tutorial from Atlassian. And once you’ve finalized those changes and committed them, you might want to check out the CloudBees Platform to deliver those changes to your users.


This post was written by Eric Boersma. Eric is a software developer and development manager who's done everything from IT security in pharmaceuticals to writing intelligence software for the US government to building international development teams for non-profits. He loves to talk about the things he's learned along the way, and he enjoys listening to and learning from others as well.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.