Git: list files at a given commit with ls-tree

To list all files in your repository as they were at a given commit, use git ls-tree with its -r and --name-only options:
$ git ls-tree --name-only -r <commit>
Replace <commit> with any commit reference: a SHA, a branch name, a tag like above, a relative reference like @~ (the commit before last), and so on.
For example, in a repository documenting puppy breeds:
$ git ls-tree --name-only -r v1.0
README.md
hound/beagle.md
hound/dachshund.md
pastoral/corgi.md
sporting/golden-retriever.md
sporting/labrador.md
toy/chihuahua.md
toy/pomeranian.md
toy/pug.md
toy/yorkshire-terrier.md
Option breakdown:
--name-onlyoutputs only file names. Without it, each line also includes the file mode bits, object type, and SHA hash:$ git ls-tree -r v1.0 100644 blob 96f1db7b7d90e0d1a0057af5a2ffbc99adb1a19b README.md ...
-rrecurses into subdirectories. Without it,git ls-treelists only the entries at the top level, showing subdirectories astreeentries.
Why not git ls-files?
git ls-files also lists files, but it reads from the index (staging area), so it can only report on the currently checked-out state.
git ls-tree reads directly from Git’s object database, so it can list the files at any commit, without needing to check it out. Pass @ (HEAD) as the commit to list files as of the latest commit, making the two commands roughly equivalent, except for any staged changes in the index.
List files within a directory
To restrict the listing to particular paths, add them after the commit and a -- separator. The -- is optional but encouraged, since it prevents any ambiguity between commit references and file names. For example, to list files within the toy/ directory at v1.0:
$ git ls-tree --name-only -r v1.0 -- toy/
toy/chihuahua.md
toy/pomeranian.md
toy/pug.md
toy/yorkshire-terrier.md
Handle newline-containing file names
If you’re scripting with this command, note that file names may contain newline characters (usually by mistake), in which case git ls-tree quotes them:
$ git ls-tree --name-only -r HEAD -- oops/
"oops/cavalier\nking\ncharles\nspaniel.md"
For accurate parsing, use the -z option to separate entries with null characters (\0) instead of newlines, unquoted:
$ git ls-tree --name-only -z -r HEAD | xargs -0 -n1 echo
😸😸😸 Check out my new book on using GitHub effectively, Boost Your GitHub DX! 😸😸😸
One summary email a week, no spam, I pinky promise.
Related posts:
Tags: git