R.M.
R.M.

Reputation: 3652

How do I get file blob SHA1s in git show (diffstat)?

Is there a way to get the SHA1 of a file blob (note: not the SHA1 of the commit) in a diffstat like format?

What I would like to do is do something like git show --stat ${commit} but instead of showing just the filename and the number of lines added/removed for that commit, I'd like to be able to see the SHA1 of the blob which corresponds to the final contents of the file.

I'm actually looking for this in the context of a larger script, where I would like to accumulate the blob SHA1s of the files which have been changed by a set of commits, so an easily parsable "plumbing" type command would be ideal. I'd also like a command that would work with either a "normal" and a merge commit (so needing a comparison reference like "HEAD^" is non-ideal).

Upvotes: 1

Views: 547

Answers (1)

R.M.
R.M.

Reputation: 3652

git diff-tree is what is needed. Despite what the diff-format page indicates, diff-tree is able to take a single tree-ish reference (e.g. a commit SHA1 or a branch name), and will do the comparison against all parents of the commit, even if it's a merge commit. (Just like git show does.)

The diff-format page explains the output format, but here's some examples:

$ git diff-tree --no-commit-id -r -c HEAD 
:100644 100644 163e1f7815c5ef7e371bfebd549d6e990a3faa6b 991c88a41f56a0b39dfee85046e6954731294ddb M  Home.md
:100644 100644 d40bd92ec40e486fa4fdda3e8e2740bfb0138a99 160d2d470b9226ed58697b96523a5579ac0dbb9e M  building/Tests.md

Here we suppressed the printing of the commit SHA1 with --no-commit-id, and specified -r to look at files in subdirectories (sub-trees) instead of just looking at the top level directory. The output lines, starting with a colon, are the files which have changed in this commit. The two SHA1s are the blobs SHA1 in the parent commit and the final SHA1 of the blob - corresponding to the contents of the file in the referenced commit.

The -c is needed for a "combined" diff in the case of merges - it tells diff-tree to make an entry for any file that's not the same as either parent. (That is, only for files which have changed from the merging process itself.)

$ git diff-tree --no-commit-id -r -c  2a6c4947dd0dcee69e7aca1c3a0ef92d7e5260f9 # merge commit
::000000 100644 100644 0000000000000000000000000000000000000000 53650eaf781e1410d8bd6fa4af29748714b7f1d4 285def5637464597883c3f363d67783176f03c2e AM    README.txt
::100644 100644 100644 e7f117c2b117dc3960250442732f0d6acfc212e6 e84b192b1e394efea15804f8de66fc0c7ee87ca7 5ca0469a65e886e56e5aedeb08359ea1627e28dd MM    Home.md

For merge commits, there's more entries, corresponding to each parent. Again, for details on the formatting and how to control it, see the diff-format and diff-tree manual pages.

Upvotes: 3

Related Questions