Thuta Learning
IntermediateDevOps & Toolsintermediate

Git Stash: Pausing Work Safely

What you'll walk away with

  • Explain the core ideas behind Git Stash: Pausing Work Safely
  • Read the diagram and trace how state or data flows through the Git/GitHub workflow
  • Decide how this applies to your own project or team

Build the mental model

An urgent bug report comes in and you need to switch branches right now, while your feature branch has half-finished, uncommitted changes. Git normally refuses to switch if it would overwrite them.

`git stash` takes every change in your working directory and staging area, tucks it into a separate storage area, and resets your working directory back to the last commit.

  • The stash isn't tied to any branch — it's stored independently, like a stack
  • `git stash pop` reapplies the most recent stash and removes it from the stack
  • `git stash apply` reapplies it while keeping a copy on the stack

You can stash multiple times before popping anything — each stash adds to the stack, and `git stash list` shows what's waiting.

text
STASH: PAUSE, SWITCH, RESUME
----------------------------
STASH: PAUSE, SWITCH, RESUME
------------------------------
working changes (uncommitted)
        |
     git stash
        v
  [ stash stack ]  <- changes stored, working dir now clean
        |
  (switch branches, do other work)
        |
     git stash pop
        v
working changes restored, exactly as before

Connect it to a real scenario

Stash

With uncommitted changes present, run `git stash` — Git reports success and `git status` confirms the tree is clean.

Switch branches

Check out wherever you need freely, then come back to your original branch.

Pop it back

`git stash pop` reapplies the changes to your working directory exactly as they were.

Pop can conflict

If the branch changed underneath it, stash pop can conflict just like a merge. The stash stays on the stack until resolved, so nothing is lost.

Try the working example

bash
git init -q -b main
git config user.name "Thuta Learner"
git config user.email "learner@example.com"

export GIT_AUTHOR_NAME="Thuta Learner"
export GIT_AUTHOR_EMAIL="learner@example.com"
export GIT_COMMITTER_NAME="Thuta Learner"
export GIT_COMMITTER_EMAIL="learner@example.com"

echo "console.log('feature in progress');" > app.js
git add app.js
GIT_AUTHOR_DATE="2026-01-06T09:00:00" GIT_COMMITTER_DATE="2026-01-06T09:00:00" \
  git commit -m "Initial commit"
git branch -M main
git branch hotfix

echo "console.log('half-written feature');" >> app.js

git status
git stash

git status

git checkout hotfix
git checkout main

git stash pop
git status
cat app.js
You should see
$ git status
On branch main
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:   app.js

no changes added to commit (use "git add" and/or "git commit -a")

$ git stash
Saved working directory and index state WIP on main: b47b383 Initial commit

$ git status
On branch main
nothing to commit, working tree clean

$ git checkout hotfix
Switched to branch 'hotfix'

$ git checkout main
Switched to branch 'main'

$ git stash pop
On branch main
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:   app.js

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

$ git status
On branch main
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:   app.js

no changes added to commit (use "git add" and/or "git commit -a")

$ cat app.js
console.log('feature in progress');
console.log('half-written feature');

5-minute try-it

Modify a tracked file without committing, then run `git stash` and confirm with `git status` that your tree is clean. Switch to another branch and back. Run `git stash list` before popping to see the stash waiting on the stack, then `git stash pop` and confirm your changes are back with `git diff`.

One important caution

`git stash` shelves both staged and unstaged changes together by default — if you only wanted to stash part of your work, you need `git stash push -- <file>` or `git stash -p` instead of a plain stash.

Popping a stash can produce merge conflicts if the branch changed underneath it — the stash isn't dropped from the stack until the conflict is resolved and you run `git stash drop` (or pop succeeds cleanly).

Git Documentation: git-stashGit & GitHub

Easy traps

  • `git stash` shelves both staged and unstaged changes together by default — if you only wanted to stash part of your work, you need `git stash push -- <file>` or `git stash -p` instead of a plain stash.
  • Popping a stash can produce merge conflicts if the branch changed underneath it — the stash isn't dropped from the stack until the conflict is resolved and you run `git stash drop` (or pop succeeds cleanly).
  • Always run `git status` before any destructive or history-rewriting command, to know exactly what state you're in.

Exercise

Modify a tracked file without committing, then run `git stash` and confirm with `git status` that your tree is clean. Switch to another branch and back. Run `git stash list` before popping to see the stash waiting on the stack, then `git stash pop` and confirm your changes are back with `git diff`.

You'll know it worked when: $ git status On branch main 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: app.js no changes added to commit (use "git add" and/or "git commit -a") $ git stash Saved working directory and index state WIP on main: b47b383 Initial commit $ git status On branch main nothing to commit, working tree clean $ git checkout hotfix Switched to branch 'hotfix' $ git checkout main Switched to branch 'main' $ git stash pop On branch main 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: app.js no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (e9ef4229ba0e959bd1d31c7dddbe7bde3b1dd675) $ git status On branch main 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: app.js no changes added to commit (use "git add" and/or "git commit -a") $ cat app.js console.log('feature in progress'); console.log('half-written feature');

Git Stash: Pausing Work Safely | Thuta Learning