Saving Work in Progress

GitGitBeginner
Practice Now

Introduction

Welcome back, Git explorer! Today, we're diving into one of Git's most useful features for managing your work-in-progress: the stash. Have you ever been in the middle of working on a feature when suddenly you need to switch to a different task? Git stash is here to save the day!

Think of Git stash as a magical drawer where you can temporarily store your unfinished work. It allows you to quickly switch contexts without committing half-done work. This is incredibly useful when you need to switch branches, pull updates, or handle an urgent bug fix.

In this lab, we'll explore how to use Git stash to save your work-in-progress, how to apply stashed changes, create branches from stashes, manage multiple stashes, and clean up your stashes. By the end of this lab, you'll have a powerful new tool in your Git toolkit that will make your workflow smoother and more flexible.

Let's get started and unlock the power of Git stash!


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL git(("`Git`")) -.-> git/SetupandConfigGroup(["`Setup and Config`"]) git(("`Git`")) -.-> git/BranchManagementGroup(["`Branch Management`"]) git(("`Git`")) -.-> git/BasicOperationsGroup(["`Basic Operations`"]) git(("`Git`")) -.-> git/DataManagementGroup(["`Data Management`"]) git/SetupandConfigGroup -.-> git/init("`Initialize Repo`") git/BranchManagementGroup -.-> git/branch("`Handle Branches`") git/BasicOperationsGroup -.-> git/commit("`Create Commit`") git/DataManagementGroup -.-> git/stash("`Save Changes Temporarily`") subgraph Lab Skills git/init -.-> lab-387492{{"`Saving Work in Progress`"}} git/branch -.-> lab-387492{{"`Saving Work in Progress`"}} git/commit -.-> lab-387492{{"`Saving Work in Progress`"}} git/stash -.-> lab-387492{{"`Saving Work in Progress`"}} end

Setting Up Your Workspace

Before we dive into stashing, let's set up a workspace to experiment in. We'll create a new directory, initialize a Git repository, and add some initial content.

Open your terminal and type these commands:

cd ~/project
mkdir git-stash-lab
cd git-stash-lab
git init
echo "## Git Stash Lab" > README.md
git add README.md
git commit -m "Initial commit"

Let's break down what these commands do:

  1. cd ~/project: This changes your current directory to the "project" folder in your home directory.
  2. mkdir git-stash-lab: This creates a new directory named "git-stash-lab".
  3. cd git-stash-lab: This moves you into the newly created directory.
  4. git init: This initializes a new Git repository in the current directory.
  5. echo "## Git Stash Lab" > README.md: This creates a new file named "README.md" with the content "## Git Stash Lab".
  6. git add README.md: This stages the new file for commit.
  7. git commit -m "Initial commit": This creates your first commit with the staged changes.

Great! We now have a repository with one commit. Let's check our status:

git status

You should see a message saying that your working tree is clean. This means we're ready to start experimenting with Git stash!

If you encounter any issues, make sure you're in the correct directory and that Git is properly installed on your system. You can check your Git installation by running git --version.

Stashing Changes

Now that we have our workspace set up, let's create some changes and learn how to stash them.

First, let's make some changes to our README.md file:

echo "This is a work in progress" >> README.md

This command appends a new line to our README.md file. Let's also create a new file:

echo "Some important notes" > notes.txt

Now, if we run git status, we'll see that we have both modified and untracked files:

git status

You should see output indicating that README.md is modified and notes.txt is untracked.

Imagine at this point you need to quickly switch to a different task, but you're not ready to commit these changes. This is where git stash comes in handy!

To stash your changes, run:

git stash

You should see output similar to this:

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

Now, if you run git status again, you'll see something interesting:

git status

You'll notice that while README.md is no longer shown as modified, notes.txt is still listed as an untracked file. This is a crucial point about git stash:

Important: By default, git stash only stashes:

  1. Changes to tracked files (files that Git is already tracking)
  2. Staged changes

Untracked files (like our notes.txt) are not included in the stash by default. This behavior ensures that Git doesn't accidentally hide new files you might not want to include in the repository.

If you want to include untracked files in your stash, you can use the -u (or --include-untracked) option:

git stash -u

After running this command, both the changes to README.md and the new notes.txt file will be stashed.

To see what's in your stash, you can use:

git stash list

You should see one or two stash entries, depending on whether you used the -u option.

Press q to exit the stash list view.

Remember, stashing is perfect for quick context switches. However, it's not a replacement for commits in your long-term workflow. Stashes are meant to be temporary storage.

Applying Stashed Changes

Now that we've stashed our changes, let's learn how to bring them back. There are two main commands for this: git stash apply and git stash pop.

Let's start with git stash apply:

git stash apply

After running this command, you might notice something unexpected. Let's check the status:

git status

You should see output similar to this:

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        notes.txt

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

Surprisingly, you'll only see notes.txt as an untracked file, and you won't see any changes to README.md. This behavior occurs because:

  1. In Step 2, we used git stash without the -u option first, which only stashed the changes to README.md.
  2. Then we used git stash -u, which stashed both the changes to README.md and the untracked notes.txt file.
  3. When we apply the stash, Git applies the most recent stash (the one created with -u), but it doesn't show changes to README.md because those changes were already included in the previous stash.

To see all the changes, including those to README.md, you can use:

git stash apply stash@{1}

Now, if you check the status again, you should see both the changes to README.md and notes.txt as an untracked file.

This situation highlights an important aspect of working with stashes: the order in which you create and apply stashes can affect the result. It's always a good practice to check the contents of your stashes before applying them, especially when working with multiple stashes.

The difference between apply and pop is that apply keeps the changes in your stash, while pop removes them from the stash after applying.

git stash clear
git stash -u
git stash list

We first clear all stashes to start fresh, then stash our changes with the -u option to include untracked files. Finally, we list our stashes to verify that the stash was created.

Let's stash our changes again and try pop:

git stash pop

You'll see similar output as before, but if you run git stash list now, you'll see that your stash is empty.

Why have both apply and pop? apply is useful when you want to apply the same stashed changes to multiple branches. pop is more commonly used when you're just resuming work on the same branch.

Creating a Branch from a Stash

Sometimes, you might realize that the changes you stashed should actually be on their own branch. Git makes this easy with the git stash branch command.

First, let's create some new changes and stash them:

echo "Feature in progress" >> README.md
echo "More notes" >> notes.txt
git stash -u

Now, let's create a new branch with these changes:

git stash branch feature-branch

This command creates a new branch named "feature-branch", checks it out, and then applies the stashed changes to it. The stash is then removed from your stash list.

You should see output similar to this:

Switched to a new branch 'feature-branch'
On branch feature-branch
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:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        notes.txt

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

This feature is particularly useful when you've stashed some experimental changes and later decide they're worth pursuing on their own branch.

Remember, after creating a branch from a stash, you'll need to commit the changes if you want to keep them:

git add README.md notes.txt
git commit -m "Start new feature"

To switch back to your master branch, use:

git checkout master

Managing Multiple Stashes

As you work with Git, you might find yourself stashing multiple sets of changes. Git allows you to manage multiple stashes easily. Let's explore how to create, list, and manage multiple stashes.

First, let's create three stashes with different changes:

## First stash
echo "Change 1" >> README.md
git stash push -m "First change"

## Second stash with untracked file
echo "Change 2" >> README.md
echo "Note 2" >> notes.txt
git stash push -u -m "Second change"

## Third stash
echo "Change 3" >> README.md
git stash push -m "Third change"

Let's break down what we did:

  1. Created first stash with a change to README.md
  2. Created second stash with both a change to README.md and a new untracked file
  3. Created third stash with another change to README.md
  4. Used the -m flag to add descriptive messages
  5. Used the -u flag for the second stash to include the untracked file

Now, let's list our stashes:

git stash list

You should see output similar to this:

stash@{0}: On master: Third change
stash@{1}: On master: Second change
stash@{2}: On master: First change

You can examine the contents of a stash without applying it:

git stash show stash@{1}

For more detail, add the -p flag to see the full diff:

git stash show -p stash@{1}

Let's create two more stashes to practice managing a larger set of changes:

## Fourth stash
echo "Change 4" >> README.md
git stash push -m "Fourth change"

## Fifth stash
echo "Change 5" >> README.md
git stash push -m "Fifth change"

Check your stash list again:

git stash list

You should now see five stashes in your list:

stash@{0}: On master: Fifth change
stash@{1}: On master: Fourth change
stash@{2}: On master: Third change
stash@{3}: On master: Second change
stash@{4}: On master: First change

Managing multiple stashes can be useful when you're juggling several tasks at once. However, try not to accumulate too many stashes as it can become confusing. Consider using branches for longer-term work.

Remember: stashes are meant to be temporary. If you find yourself keeping stashes for a long time, consider using feature branches or committing your changes instead.

Cleaning Up Stashes

As you use stashes in your workflow, you might accumulate stashes that you no longer need. It's a good practice to clean up your stashes regularly to keep things organized.

To remove a single stash, you can use the drop command we saw earlier:

git stash drop stash@{2}

This removes the oldest stash in our list.

If you want to remove all your stashes at once, you can use:

git stash clear

Be very careful with this command! It will remove all your stashes and cannot be undone.

Another useful command is git stash pop, which we saw earlier. It applies the most recent stash and then removes it from the stash list:

git stash pop

Remember, it's generally a good practice to keep your stash list short. Stashes are meant for temporary storage of work-in-progress. If you find yourself accumulating many stashes, it might be a sign that you should commit your changes more frequently or create feature branches for longer-term work.

Summary

Congratulations, Git stash master! You've just added a powerful new tool to your Git toolkit. Let's recap the key concepts we've covered:

  1. Stashing Changes: You learned how to temporarily store your work-in-progress using git stash.
  2. Applying Stashed Changes: You discovered how to bring back your stashed changes using git stash apply and git stash pop.
  3. Creating Branches from Stashes: You saw how to turn a stashed set of changes into a new branch with git stash branch.
  4. Managing Multiple Stashes: You learned how to work with multiple stashes, applying and showing specific stashes as needed.
  5. Cleaning Up Stashes: You practiced good stash hygiene by learning how to remove individual stashes and clear all stashes.

Git stash is an incredibly useful feature that allows you to quickly switch contexts without committing half-done work. It's perfect for those moments when you need to quickly switch tasks or branches.

Remember, while stashes are useful, they're meant to be temporary. For longer-term work, it's usually better to commit your changes or create a new branch. Use stashes wisely, and they'll help you keep your workflow smooth and flexible.

Other Git Tutorials you may like