Stash untracked files without losing the context
Use Git stash’s include-untracked option (-u) to save untracked files alongside tracked changes. Ignored files remain in place unless you choose the broader all option, so inspect what each choice would include before saving.
Choose which files belong in the stash
An untracked file is present in the working directory but has not been added to the index. An ignored file is also untracked, but an ignore rule tells Git to leave it out of ordinary untracked listings. They are not interchangeable categories for this task. The stash reference distinguishes including untracked files from including both untracked and ignored files1.
Start by inspecting the working tree and the relevant ignore rules. A scratch file may be a disposable output, an essential draft or a local secret; the filename alone does not decide. A stash is a local repository object, not a secure vault or a substitute for a backup. In particular, including an ignored file can put material you meant to keep local into the repository’s object storage.
Read the two passes
The first pass edits a tracked note, creates an untracked scratch file and creates a log matched by the example’s ignore rule. The include-untracked option saves the note and scratch file. The script verifies that the scratch file is absent afterward while the ignored log remains. That result answers this example’s question; it does not mean every ignored file in a different repository is safe to remove.
After the first pop restores the draft, the second pass uses the all option. Now the script checks that both the untracked draft and ignored log have left the working directory. It then pops that stash and checks that both return. Each pass starts with the same three pieces of local work, so the difference is the selected file category, not a change in the initial state.
Decide how to restore
Restoring a stash can conflict with the current working tree. The example pops immediately in the same branch without intervening edits; it does not exercise conflicts or a different destination. Inspect the stash and the destination before relying on a pop. The separate apply and pop guide shows why an unsuccessful pop and a successful pop leave different stash states.
When preserving staging distinctions matters, treat that as another requirement rather than assuming every restored path returns to the same staged state. The example checks file presence, not restoration of an earlier index arrangement. If another task needs the exact staging selection, inspect both the staged and working differences before and after restoring, and keep the original information until you have verified the result.
Check what a clean-looking tree hides
A short status listing can omit ignored files by design. That makes a clean-looking working tree an incomplete inventory of local files. Before using the broader option, determine which ignored paths are present and whether the operation will move files needed by another process. A generated cache can usually be recreated; a local configuration or unpublished draft may need deliberate handling.
The word “all” does not mean every possible repository state is portable. A stash is local to the repository and may be affected by its own lifecycle. It does not automatically follow a branch to another clone. Record the purpose of the saved work, verify the target before restoration and keep a separate copy when the contents are important enough that a conflict or failed restoration would be costly.
Preserve the distinction between saved and shareable work
The local stash can contain both tracked changes and the untracked file content selected by the operation. The name supplied in this example is a reminder of purpose; it is not a description of every file or a record of why a particular change belongs together. Inspect the saved content before applying it to a different task. If the same path already exists at the destination, a restoration may need a decision about which content to keep.
The two demonstrations deliberately restore before starting the next pass. That sequence prevents the second result from being confused with a remaining file from the first. It also means the example does not compare a stack of several saved entries or test selecting a non-top entry. Before clearing or dropping any saved entry in real work, make sure the relevant changes are present in a suitable place and can be recovered if needed.
Git’s available options are not a substitute for a file inventory. A generated log may be ignored because it contains local material that should not travel; a scratch note may be untracked because it is unfinished. The choice to include either depends on the contents and the next task. A separate copy and a clear record of the state give you a way to verify restoration rather than assuming a clean directory proves everything was preserved.
Run the complete local example
Before running: use an empty directory. This script creates example-work, including a fictional working repository and a local bare remote; it stops if that directory already exists. The all option temporarily removes an ignored file in this fictional directory; inspect real ignored files and keep a safe copy before using it elsewhere. Review the commands first and do not point it at a real project.
Download the complete MIT-licensed example and run it with Git 2.56.0. The printed script is the tested file. The two recorded runs used fresh directories and produced the same output; the remote in this example is a local directory.
#!/bin/sh
# SPDX-License-Identifier: MIT
set -eu
export TZ=UTC LC_ALL=C
export GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null
export GIT_AUTHOR_NAME='Example Author' GIT_AUTHOR_EMAIL='author@example.invalid'
export GIT_COMMITTER_NAME='Example Author' GIT_COMMITTER_EMAIL='author@example.invalid'
export GIT_AUTHOR_DATE='2026-10-27T12:00:00+00:00'
export GIT_COMMITTER_DATE='2026-10-27T12:00:00+00:00'
test "$(git --version)" = 'git version 2.56.0'
mkdir example-work
cd example-work
git init --bare -q --template= --initial-branch=main remote.git
git init -q --template= --initial-branch=main project
cd project
git config commit.gpgsign false
git config core.autocrlf false
git remote add origin ../remote.git
printf 'base\n' > tracked.txt
printf '*.log\n' > .gitignore
git add tracked.txt .gitignore
git commit -qm 'Base files'
git push -q -u origin main
printf 'changed\n' >> tracked.txt
printf 'draft\n' > scratch.txt
printf 'secret\n' > private.log
git stash push -q -u -m 'include untracked'
test ! -e scratch.txt
test -f private.log
printf 'After -u: scratch saved; ignored log remains\n'
git stash pop -q
test -f scratch.txt
git stash push -q -a -m 'include ignored'
test ! -e scratch.txt
test ! -e private.log
printf 'After -a: scratch and ignored log saved\n'
git stash pop -q
test -f scratch.txt && test -f private.log
printf 'After pop: both files restored\n'
Both runs produced:
After -u: scratch saved; ignored log remains
After -a: scratch and ignored log saved
After pop: both files restored
The script leaves example-work in the directory where it ran, including the local repositories and their data. After inspecting the result, remove that example directory when it is no longer needed. Do not remove a directory with the same name in a real project unless you have verified its contents and decided it is safe to delete.
Not covered on this page
- Stash conflicts or restoration on another branch.
- Recovery of dropped or expired stashes.
- Restoration of an original staging selection.
Sources
-
git-stash — Git 2.56.0. Git 2.56.0; checked 27 October 2026 UTC. ↩
How we test: methodology. Found a mistake? Corrections.