The 12 Days of Git, Day 11: Stashing Changes with Git until You Need Them

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmailby feather

On the eleventh day of Christmas, my true love gave to me… eleven rapid changes.

In the previous lesson, we learned about merging different versions with Git in order to resolve conflicting sets of changes. Today, we’re going to learn about stashing any changes you are working on, in case something more pressing comes up. You can deal with the more pressing issue, and then go back to the changes you were working on before.

If you are following our song, “The Twelve Days of Git,” here are the verses so far:

  1. The 12 Days of Git: Learn Git over the Holidays
  2. The 12 Days of Git, Day 2: Tracking Files with Git
  3. The 12 Days of Git, Day 3: Viewing Git History
  4. The 12 Days of Git, Day 4: Double-checking Changes with Git
  5. The 12 Days of Git, Day 5: Sharing Changes Remotely with Git
  6. The 12 Days of Git, Day 6: Making a Copy of a Git Repository
  7. The 12 Days of Git, Day 7: Keeping Your Git Repository Up-To-Date with Others’ Changes
  8. The 12 Days of Git, Day 8: Using Git to Experiment Safely
  9. The 12 Days of Git, Day 9: Using Remote Branches with Git
  10. The 12 Days of Git, Day 10: Merging Different Versions with Git

Have you ever been in the middle of something, and someone interrupted you to do something else right then? You had to stop what you were doing. Well, when what you are doing is adding related bits to several files, and you have to fix a bug in one file immediately, what can you do?

You shouldn’t have to cut the new bits you’ve already typed, or save your intermediate versions under new names. Maybe you’re not quite ready to commit a version of what you’re working on. (Commits whose messages are “Halfway done with X” don’t reflect the logical flow of your work.)

Git has a good option for saving the current state of files to a temporary holding area. Each temporary saved state is called a stash. Let’s run through a simple example of using a stash.

In your local repo, go back to the master branch, and start editing the index.html and main.css files to add a Locations feature. Only make the changes highlighted below.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Father Christmas Tracker: Bringing the North Pole to You</title>
    <link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
    <h1>Father Christmas Tracker</h1>
    <p>Bringing the North Pole to you since 2015</p>
    <ol class="locations">
        <li>Apia, Samoa</li>
        <li>Wellington, New Zealand</li>
        <li>Majuro, Marshall Islands</li>
    </ol>
</body>
</html>
body {
    background-color: #222;
    color: #f0f0f0;
}

h1 {
    color: #ff0000;
    text-align: left;
}

.locations {
    background-color: gray;
    font-style: italic;
    padding-bottom: 1em;
    padding-top: 1em;
}

Save those changes to the two files, but do not stage or commit them yet. If you run git diff, you’ll see the lines waiting to be committed.

Now, imagine that you get word that Santa Tracker has been banned in Britain! You have to change Father Christmas back to Santa immediately, but you’re not done with your Locations feature yet.

Run the following command in the terminal:

git stash save locations

You’ll see output like this:

Saved working directory and index state On master: locations
HEAD is now at 7f67565 Change Santa to Father Christmas

Now, if you run git status, Git will tell you that your working directory is clean, and git diff will not list any changes. Open those two files again, and you will see that your new changes are gone.

Change the name Father Christmas back to Santa in both places in index.html. Add and commit the name change.

git commit -am'Change Father Christmas back to Santa'

Now, let’s get back to what we were working on before. First, let’s list what stashes are available.

git stash list

This will output.

stash@{0}: On master: locations

You can store more than one stash, and the most recent one is always stored first in the list, and pushes the other ones down the list, like a stack of plates in a cafeteria. The first stash is numbered 0, the second one would be numbered 1, and so on. Each stash also list the branch it was created from. If you gave it a name, like we did, the name will be listed at the end of the line. (If you need a stash for a very short period of time, you can just type git stash because the default action is to save a stash, and it will be saved as <code.stash@{0}, without a name.)

You can also see what files changed in a stash by typing:

git stash show

This will output:

 index.html | 5 +++++
 main.css   | 9 ++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

If you really want to dig into a stash to see if you want to restore it, use git stash show -p to see a full diff of the stash with the current version.

We know this is the stash we are looking for; so, let’s bring back those changes. We do this by typing:

git stash pop

The output will look like this:

Auto-merging index.html
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
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.html
	modified:   main.css

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (fe197af761f499e286a3ac0b93e894f2a1657538)

Your changes are back, and running git stash list will show that the stashed copy is gone.

I’m exhausted from all this stashing. I’m going to add and commit this work at this point after all.

Check back tomorrow, when we’ll learn about The 12 Days of Git, Day 12: Fixing Mistakes with Git.

To see all the options available for the commands we’ve discussed today, check them out in the online Git reference:

Leave a Reply

Your email address will not be published. Required fields are marked *