Stashing untracked and ignored files Jump to heading
A plain git stash saves changes to tracked files only. New files you have not added yet stay in the working tree, which surprises people: they stash, switch branches, and find their new module sitting there on the other branch, or they stash to get a clean tree and the build still picks up the new file. -u (--include-untracked) includes new files. -a (--all) goes further and includes ignored files too β build output, dependency directories, local configuration. That second option is almost never what you want and is a common way to stash gigabytes of node_modules or a .env file full of credentials. This page explains the three modes and how to use them safely, within stashing and work-in-progress recovery.
When to use this approach Jump to heading
- You stashed, and new files you created were left behind.
- You need a truly clean working tree, including new files, for a test or a branch switch.
- Someone suggested
git stash -aand you want to know what it does before running it. - You are deciding between stashing and other ways to park work, as in stash vs worktree vs WIP commit.
Step 1 β Know what each mode includes Jump to heading
There are three classes of file: tracked (Git knows them), untracked (new, not ignored), and ignored (matched by .gitignore). Each stash mode takes a different set.
git status --short --ignored
# M src/export/schedule.py tracked, modified
# ?? src/export/prototype.py untracked
# !! node_modules/ ignored
# !! .env ignored Step 2 β Include new files with -u Jump to heading
-u stashes tracked changes and untracked files, then removes the untracked files from the working tree. After it, git status shows a clean tree apart from ignored files.
git stash push -u -m "export prototype, including new files"
git status --short # clean
ls src/export/prototype.py 2>/dev/null || echo "new file stashed" Untracked files are stored in a third parent of the stash commit, which is why git stash show does not list them by default.
git stash show --include-untracked stash@{0} # Git 2.32+
git show --stat 'stash@{0}^3' # any version: the untracked-files commit Step 3 β Avoid -a unless you mean it Jump to heading
-a stashes and then deletes ignored files: your dependency directory, build output, editor settings, local environment files. Restoring them means applying a potentially huge stash; and until you do, the project will not build.
# Check the size of what -a would take before ever running it
git status --short --ignored | awk '$1=="!!"{print $2}' | xargs du -sh 2>/dev/null | sort -h | tail β οΈ SAFETY WARNING:
git stash -adeletes ignored files from the working tree after stashing them, including dependency directories and local secrets files. The stash also keeps a copy of those secrets in your repositoryβs object store, where tools that copy or upload.gitcan pick them up. If you ran it by accident,git stash poprestores everything; if you want to discard the stash, rungit stash dropand thengit gc --prune=nowto remove the stored copy.
Step 4 β Clean without stashing when you do not need the files back Jump to heading
Sometimes the goal is a clean tree and the new files are disposable β generated test output, scratch files. Then git clean is the right tool, not a stash. Always run it with -n first.
git clean -n # list untracked files that would be deleted
git clean -n -d # include untracked directories
git clean -f -d # delete them
git clean -n -X # only ignored files (e.g. stale build output) β οΈ SAFETY WARNING:
git clean -fpermanently deletes untracked files; they are not stored anywhere in Git and cannot be recovered with the reflog or fsck. Always preview with-n. If any listed file might be wanted, stash it with-uinstead.
Step 5 β Restore untracked files cleanly Jump to heading
Popping a stash that contains untracked files fails if a file with the same path now exists in the working tree β Git will not overwrite it. Move the conflicting file aside, then pop.
git stash pop
# error: src/export/prototype.py already exists, no checkout
mv src/export/prototype.py /tmp/prototype.py.new
git stash pop
diff /tmp/prototype.py.new src/export/prototype.py Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Why arenβt untracked files in git stash show output? Jump to heading
They are stored in a separate parent commit of the stash, and show only diffs against the first parent by default. Use --include-untracked (Git 2.32+) or inspect stash@{n}^3 directly.
Can I make -u the default? Jump to heading
Not through a dedicated setting. An alias such as git config --global alias.su 'stash push -u' gives you a short command that always includes untracked files.
Does stashing untracked files respect .gitignore? Jump to heading
Yes. -u takes only untracked files that are not ignored. Ignored files are taken only with -a.
Related Jump to heading
- Stashing & Work-in-Progress Recovery β the parent topic.
- Stashing Only Some Files with Pathspecs β combining
-uwith path selection. - Recovering a Dropped Stash β when a stash with new files goes missing.
- Keeping Secrets Out of CI Logs β other places local secrets leak.