I don't think you can do this with git ls-files
itself (a minor shame since it's otherwise pretty handy for these sorts of things).
Ultimately, to Git, the fact that a file doesn't exist in the work-tree is not important for the next commit. The commit uses whatever's in the index / staging-area. The main focus of git ls-files
is on the index contents, hence options like --stage
and --debug
. However, the presence of the --others
option proves that git ls-files
can scan the work-tree. Having scanned the work-tree, it can then show you which files are in the work-tree but missing from the index: --others
. This list can be further subtracted-away-from, using --exclude-standard
and the like.
Your particular case is one where, instead of taking a list of work-tree files and subtracting away those that are in the index, you would like to take a list of index files and subtract away those that aren't in the work-tree. That is, if we define I as the set of index files and W as the set of work-tree files, we we see that git ls-files
can easily compute W \ I. We'd like to have it compute I \ W, the set of files that are in the index but missing from the work-tree, so that we can remove them from git ls-files
's output.
Alas, there's no such option. That leaves you with git diff-files
, which can easily compute this set of files: git diff-files --name-only --diff-filter=D HEAD
gets you the files that are in the index but missing from the work-tree. Use this list to remove filenames from the git ls-files
output, and you have what you need.
Important sidebar
Often, files that are missing from the work-tree, but are present in the index, are in this state by mistake, and the correct thing to do is to extract them from the index to the work-tree. Also, any time you plan to do something with the set of files that are in the index right now, you should account for the fact that the copies of those files in the work-tree may differ from the copies in the index. For instance, a Git pre-commit hook might be intended to make sure that files are correctly formatted for some source language: that running them through clang-format
or black
would leave them unchanged, for example.
Testing for this by examining the work-tree files is fundamentally wrong, because Git isn't going to build the commit from the work-tree. What this means is that these tools should extract the entire index into a temporary (new and empty) work-tree somewhere else in the file system, and then run the formatter, or whatever tool is to be used, on that temporary work-tree. The result of this process tells you whether the commit should proceed. You then remove the temporary work-tree (i.e., clean up after yourself) and provide the appropriate "can commit" / "no, don't commit" exit status.