You can use git ls-tree --full-tree -r HEAD
on a bare repo to get all the files in that repo, but I want that list for specific commits.
I.e. I want to walk though a repo commit by commit from the first commit until I'm at HEAD and see how the file tree has evolved. I only care about the files and paths, I don't actually care about the contents.
Is there a way to do this on a bare repo? I want this on a bare repo because we have some very large repos and doing a checkout for each commit would be far too costly in CPU time.
Sure, just replace HEAD
with any commit-or-tree identifier, such as an SHA-1 or any of the specifiers allowed by gitrevisions
.
To get SHA-1 IDs, use git rev-list
. For instance, to work from the current commit (HEAD
) back to the root following only first parents at each merge:
git rev-list --first-parent --topo-order HEAD | while read rev; do
git ls-tree --full-tree -r $rev
done
To run through the same set of revisions in the other order, add --reverse
to the arguments to git rev-list
.
If you want to follow all parents at merges, you can simply omit --first-parent
. The --topo-order
restriction will ensure that parent commit IDs come before (or with --reverse
, after) all their children. Without a specific sort, you get the commits in reverse (or with --reverse
, forward) order by commit-date.
(If you're going to track the tree as it evolves but also want to handle merges nicely, you may need a more complex operation here, where you have git rev-list
produce the parent and child commit IDs together, since even with --topo-order
or some other sorting criterion keeping parent/child relationships together, it's not going to be obvious, from a flattened graph, exactly where the merge happened. Read the git rev-list
documentation thoroughly for this. Using --first-parent
simplifies the job enormously since it gives you a simplified, strict parent/child ordering.)