Since the various answers here so far seem to have their own intricacies/limitations, I wanted to provide a few more alternatives that cover all of the specific edge cases that I personally have needed.
tl;dr
List staged (without deleted) files:
git diff --staged --diff-filter=d --name-only
List unstaged (without deleted) files:
git diff --diff-filter=d --name-only
List unstaged/untracked files:
git ls-files --modified --others --exclude-standard
Stashing only staged files (originally from this StackOverflow answer, but tweaked slightly):
git stash push --include-untracked -- $(git diff --staged --diff-filter=d --name-only)
Stashing only unstaged (not untracked) files:
git stash push --keep-index -- $(git diff --diff-filter=d --name-only)
Stashing unstaged and untracked files:
git stash push --keep-index --include-untracked -- $(git ls-files --modified --others --exclude-standard)
Stashing staged/unstaged files, while also keeping the staged files in your index as well:
git stash push --keep-index
Stashing staged/unstaged/untracked files, while also keeping the staged files in your index as well:
git stash push --include-untracked --keep-index
Full Explanation
git stash push
allows us to provide a <pathspec>
, and only stash the files that match it:
git stash push -- <pathspec>
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>…]
Save your local modifications to a new stash entry and roll them back to HEAD (in the working tree and in the index). The part is optional and gives the description along with the stashed state.
<pathspec>…
This option is only valid for push
command.
The new stash entry records the modified states only for the files that match the pathspec. The index entries and working tree files are then rolled back to the state in HEAD only for these files, too, leaving files that do not match the pathspec intact.
-u
, --include-untracked
, --no-include-untracked
When used with the push
and save
commands, all untracked files are also stashed and then cleaned up with git clean
.
git diff
allows us to list the currently unstaged files with --name-only
:
git diff --name-only
git diff [<options>] [--] [<path>…]
This form is to view the changes you made relative to the index (staging area for the next commit).
--name-only
Show only names of changed files.
--diff-filter=\[(A|C|D|M|R|T|U|X|B)…\[*\]\]
Select only files that are Added (A
), Copied (C
), Deleted (D
), Modified (M
), Renamed (R
), have their type (i.e. regular file, symlink, submodule, …) changed (T
), are Unmerged (U
), are Unknown (X
), or have had their pairing Broken (B
). Any combination of the filter characters (including none) can be used.
Also, these upper-case letters can be downcased to exclude. E.g. --diff-filter=ad
excludes added and deleted paths.
git ls-files
allows us to list both the --modified
files AND the untracked (--others
) files:
git ls-files --modified --others --exclude-standard
git-ls-files
- Show information about files in the index and the working tree
-m
, --modified
Show modified files in the output
-o
, --others
Show other (i.e. untracked) files in the output
--exclude-standard
Add the standard Git exclusions: .git/info/exclude, .gitignore in each directory, and the user’s global exclusion file.