Lesson 26 · Recovery
Stash work and resume it safely
Set an unfinished edit and a new note aside with stash, bring them back with Apply, and see what Pop does when it conflicts: the stash stays until you decide.
- Level: Intermediate
- 9 min read
- 5 min video
- Updated
- Before this lesson: Stage the intended snapshot and make your first commit, Resolve merge and rebase conflicts
Progress saved in this browser.
Playing loads the video from YouTube (privacy-enhanced mode).
What you will learn
- Choose what goes into a stash: tracked edits, untracked files, or only what is staged.
- Explain why Apply keeps the stash and Pop removes it only after a clean apply.
- Verify that both the edit and the note came back and the branch did not move.
- Recover from a Pop conflict without losing the stash.
Before you start
You are on private/stash-hint, a branch from lesson 18's result, with one commit that adds docs/stash-conflict.md ("Use a fictional address."). In your work tree you have an unfinished edit to that file and a new file, docs/signup-hint.md, that Git has never seen. Someone asks you to switch to something else, so you want both set aside, without committing half-done work.
Everything is local and on the Free plan (GitTree asks you to sign in): no hosting account, no provider, no internet. Every identity is fictional (example.com). Never run this lesson in a real project.
Make the changes in GitTree or with the native Git commands, not both in the same copy. Reading the result is always safe. The menu labels come from GitTree 2.0's own strings and the native commands were run with Git 2.43 in disposable copies. The GitTree steps were not run on macOS, Windows or Linux.
Concept and state effects
Stash stores your local changes as Git objects and then cleans the work tree back to the last commit. It is a short interruption tool, not a backup and not a replacement for a branch you want to keep.
A stash holds tracked edits by default. Untracked files are left behind unless you ask for them, which Git does with --include-untracked. GitTree's Stash Changes… dialog has Include untracked files switched on when it opens; check it anyway. Ignored files are a different category and are not stashed here. Only staged changes stashes just what is in the index, and Keep staged changes in place too leaves the index as it was.
Apply Stash puts the changes back and keeps the stash in the list. Pop Stash applies it and removes the entry only if the apply was clean. If it conflicts, the stash stays, and you resolve the conflict in the work tree. GitTree's Apply and Pop do not restore the staged state; git stash apply --index does that, but the app does not use it, so staged edits come back unstaged.
Stashing and applying never move the branch or make a commit. Only the work tree and a stash entry change.
Prepare the exact project state
Start from a separate ordinary copy of the project as lesson 18 left it and leave your original gittree-features untouched. Create the branch, save DOC_STASH_BASE and commit it. Then save DOC_STASH_WORK over the same file and DOC_HINT as a new file, without staging either. DOC_STASH_OTHER and STASH_RESOLVED are used only in the separate conflict copy.
Complete file inputs
Save only at the phase named below. These are full UTF-8/LF bodies with a final newline; never paste Markdown fences. Unchanged runnable files inherit the named input. Versions in separate variants must not overwrite the original.
docs/stash-conflict.md — DOC_STASH_BASE
Use a fictional address.docs/stash-conflict.md — DOC_STASH_WORK
Use a complete fictional email address.docs/signup-hint.md — DOC_HINT
Unfinished signup hint: use fictional data only.docs/stash-conflict.md — DOC_STASH_OTHER
Do not send the address anywhere.docs/stash-conflict.md — STASH_RESOLVED
Use a complete fictional email address. Nothing is sent.In GitTree
Open the palette with Command+Shift+P (Ctrl+Shift+P on Ubuntu). Stash entries are listed in the left panel under Stashes; a stash's actions are in its right-click menu.
- Build the branch and the two unstaged changes as the next section shows. Read the changes list:
docs/stash-conflict.mdis modified anddocs/signup-hint.mdis new. - Open the palette and run Stash Changes…. In the dialog set Message to
signup hint rehearsal. Only staged changes is off. Include untracked files is on. Keep staged changes in place too is off. Choose Stash. - Wait for the notice "Stashed your changes." The changes list is empty, the note is gone from disk and the stash appears under Stashes.
- Hover the stash row: its tooltip says "Includes untracked files". Right-click it and choose Show Stash: the graph selects the stash and the right panel lists its tracked change,
docs/stash-conflict.md. The untracked note is kept in a separate part of the stash. - Right-click it again and choose Apply Stash. The notice says "Applied the stash; it is still in the list."
- Check the result:
docs/stash-conflict.mdis modified again,docs/signup-hint.mdis back as an untracked file, the branch tip is the same commit and the stash is still listed. - Separate conflict copy. In a second copy, after the stash, commit DOC_STASH_OTHER to the same file. Right-click the stash and choose Pop Stash. The warning says "The stash conflicts with your changes: resolve the conflicts. The stash is kept."
- The conflicted file is listed with Conflicted. Open it, write STASH_RESOLVED in the output and choose Save and Mark Resolved. The stash is still there. When you are sure the work is safe, right-click it and choose Delete Stash…; the dialog says it is removed from the list and kept in the recovery snapshots. GitTree's Undo does not restore a deleted stash yet (lesson 30), so treat deleting as final.
For every ordinary commit in the course: Summary is the stated subject, Description is empty and the options Amend Previous Commit, Skip Hooks, Add Signed-off-by, Different Author, Push After Commit and Allow Empty Commit stay off.
In the terminal
In a separate copy of lesson 18's result:
git switch --create private/stash-hintSave DOC_STASH_BASE as docs/stash-conflict.md, then:
git add -- docs/stash-conflict.md
git commit --quiet -m "docs: establish the stash conflict baseline"Save DOC_STASH_WORK over docs/stash-conflict.md and DOC_HINT as docs/signup-hint.md, without staging. Then stash both:
git stash push --include-untracked --message "signup hint rehearsal"
git status --short
git stash list --format=%sOn private/stash-hint: signup hint rehearsalThe status prints nothing: the tree is clean. Keep an untouched copy of this state for the conflict, then apply:
git stash apply 'stash@{0}'
git status --short
git stash list --format=%s
git rev-parse HEAD M docs/stash-conflict.md
?? docs/signup-hint.md
On private/stash-hint: signup hint rehearsalBoth bodies are back, the stash is still listed and HEAD is the commit it was. Without --include-untracked, the same push leaves docs/signup-hint.md on disk and stashes only the edit.
In the separate copy, save DOC_STASH_OTHER and commit it, then pop:
git add -- docs/stash-conflict.md
git commit --quiet -m "docs: change the stash target"
git stash pop 'stash@{0}'
git ls-files --unmerged
git stash list --format=%sPop exits with 1 and prints "CONFLICT (content)" and "The stash entry is kept in case you need it again." Three unmerged entries are listed, the file holds conflict markers, docs/signup-hint.md is restored, and the stash is still listed. There is no merge or rebase to continue: save STASH_RESOLVED and run git add -- docs/stash-conflict.md. To park the work on its own branch instead, git stash branch rescue-hint 'stash@{0}' creates the branch at the commit where the stash was made, applies it, and removes the stash only then.
Result
Where you end: in the first copy the tree has the edit and the note again, HEAD has not moved, and the stash is still listed. In the conflict copy Pop reported the conflict, the stash survived, and your resolution is staged. No commit was made by any stash command, and nothing was pushed.
Common mistakes
- Forgetting that untracked files are not stashed unless you include them.
- Assuming Pop deleted the stash after a conflict. It did not.
- Applying twice when the first apply already worked, then wondering about duplicate changes.
- Using a stash as a long-term store. Name useful work with a branch.
If something goes wrong
After a Pop conflict, leave the stash in place, resolve the file, and check the result before you delete anything. If you applied to the wrong branch, discard that work only after you have confirmed the stash still holds it. Create Branch from Stash… gives the stash its own branch at the commit where it was made.
Check your understanding
Answer each question, then read why. Questions marked “Required” count toward completing the lesson.
0 of 6 correct
Answer the required questions correctly to complete the lesson.
Checked in this browser.
Practice
Prove the tree was clean after the stash, that Apply restored both files, and that the stash is still listed. Predict what would differ if Include untracked files were off. In the conflict copy, prove the stash survived the Pop.
Your own confirmation: the site cannot see your computer.
To complete the lesson, answer the required questions correctly and confirm the practical exercise.
Recap
- Choose the stash options on purpose.
- Apply keeps the entry.
- A conflicting Pop keeps it too.
Related
Glossary terms introduced
Stash — مخبأ; apply — تطبيق; pop — تطبيق وحذف; untracked — غير متتبَّع.
Video transcript
The narration of the video, cue by cue.
Show the transcript
- Set unfinished work aside, and bring it back safely.
- A stash holds your edits on a shelf, and cleans the work tree.
- Apply brings the changes back and keeps the entry. Pop removes it, if clean.
- Make a branch with one commit, then edit the file and add a new note.
- In the changes list: one modified file, and one new file.
- Write down the current commit. It must not move.
- Open the palette and run Stash Changes.
- Give it a message you will recognize.
- Only staged is off. Include untracked is on. Keep staged is off.
- Ignored files are a different category, and do not go in.
- Choose Stash, and wait for the notice.
- The changes list is empty, and the stash is listed.
- The tooltip says untracked files are included. Show Stash lists its files.
- Right-click the stash, and choose Apply Stash.
- The notice says the stash is still in the list.
- Both are back: the edit, and the note.
- The branch tip is the same commit. No stash command made one.
- And the stash is still on the shelf.
- In the terminal, git stash push with include untracked, then the status.
- The list shows the message, with the branch name first.
- git stash apply brings both back.
- The stash is still listed, and HEAD is the same.
- Without that option, the note stays on disk.
- In the conflict copy, we commit another change first, and then pop.
- The warning says the stash is kept. The file is conflicted.
- Resolve the file, and mark it resolved. The stash is still there.
- Delete the stash only when you are sure. Or give it its own branch.
- Practice: prove clean, restored, and kept. Then predict without include untracked.
- Next, learn what reset soft, mixed and hard each change.