I created a new sub-directory and created a new file in it. I then
added all to the Staging Area.
git ls-files -s shows the new file, but does not show the tree that represents the sub-directory.
Is there a way to show the contents of the Staging Area using
git ls-tree? Is there a ref pointing to the index?
The short answer is no.
The index itself doesn’t contain trees,1 and file names as stored in the index are full path names (with forward slashes, even if your host OS uses backward slashes). The
git ls-tree command reads tree entries (only), not the index; the
git ls-files command reads the index;2 and never the twain shall meet.
1Except, that is, for an extension that can cache a tree object seen earlier. This is meant to speed up a future
git ls-files command also needs, sometimes, to read the working tree. Confusingly, the term working tree has nothing at all to do with Git’s internal tree objects. The term "working tree" encompasses an OS-provided entity, where the OS allows Git to store the de-compressed, un-Git-ified files extracted from a commit. The extraction process consists of reading a commit to find a tree object—the top level tree that stores the snapshot that goes with the commit—and then reading that tree and, recursively, any sub-trees to which that tree refers. These provide the path name components, such as
file, which the recursive-reading process joins up into a simple string,
path/to/file. That simple string winds up in Git’s index aka staging area aka cache; Git then uses the string—in cooperation with the OS, which might demand backwards slashes3—to create or delete or update folders and files-within-folders as necessary.
3Fortunately, even on Windows, the underlying OS allows forward slashes in path-names. (I don’t know whether various Git-for-Windows versions make use of this.) In any case, Git itself is constantly having to analyze paths and handle the inevitable "D-F conflicts" that occur: commit
badf00d might have a file named
path/a, while commit
deadcab has a file named
path/a/b. Between the two,
path/a has a D-F conflict: it needs to be a directory (sometimes) and a file (sometimes).
Personally, I think it might be interesting to have an OS in which
path/to can be opened and used as a file while, at the same time, having
path/to/file available as a path name for a file. The OS’s equivalent of
lstat would need to be able to tell you that
path/to is both directory and file, whenever there are files visible underneath
path/to. But all the systems on which Git runs dictate that
path/to can only be one of these.
Answered By – torek