Adam Johnson
Read post

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

A concise guide to using `git ls-tree` with the `-r` and `--name-only` flags to list all files in a repository as they existed at any given commit. Covers the difference between `git ls-tree` (reads from Git's object database, works on any commit) and `git ls-files` (reads from the index, limited to current checkout). Also explains how to restrict output to a specific directory using path arguments, and how to handle file names containing newlines when scripting by using the `-z` flag for null-delimited output.

    #git#cli#version-control
Yesterday•2m read time•From adamj.eu
Post cover image
Table of contents
Why not git ls-files ?List files within a directoryHandle newline-containing file namesFin

Questions this post answers

How do I list all files in a Git repository as they were at a specific commit without checking it out?

Use `git ls-tree --name-only -r <commit>`, replacing `<commit>` with any commit reference — a SHA, branch name, tag, or relative reference like `@~`. The `-r` flag recurses into subdirectories, and `--name-only` omits the mode bits, object type, and SHA hash. Unlike `git ls-files`, `git ls-tree` reads directly from Git's object database and works on any commit. Developers navigating Git history and commit archaeology share tips like these on daily.dev.

What is the difference between git ls-tree and git ls-files?

`git ls-files` reads from the index (staging area) and can only report on the currently checked-out state, including any staged changes. `git ls-tree` reads from Git's object database and can list files at any commit without checking it out. Passing `@` (HEAD) to `git ls-tree` makes the two roughly equivalent, except for staged changes. Teams standardizing Git workflows find comparisons like this on daily.dev.

How do I handle file names with newlines when scripting git ls-tree?

Use the `-z` flag to separate entries with null characters instead of newlines, which also prevents quoting of unusual file names. Pipe the output to `xargs -0 -n1` for safe per-entry processing: `git ls-tree --name-only -z -r HEAD | xargs -0 -n1 echo`. Without `-z`, `git ls-tree` quotes file names containing newlines, which can break naive line-by-line parsing. Developers writing Git automation scripts encounter edge cases like this — daily.dev surfaces the practical details.

12 Impressions
Adam Johnson's image
Adam Johnson

AdamJ's platform covers topics related to software development, technology trends, and coding tutor...

54 Followers

•

444 Upvotes

Would you recommend this post?

Copy link
WhatsApp
Facebook
X
New Squad
  • © 2026 Daily Dev Ltd.
  • Guidelines
  • Explore
  • Tags
  • Sources
  • Squads
  • Leaderboard