1

I need to get a list of all the files changed in a commit — and their hashes — for comparison against a list of the same provided by our core review service. I see lots of ways to get the list of files, but none that list the hashes as well.

Is there a way to get these, short of parsing the actual diff output for the index lines?

Ben Blank
  • 54,908
  • 28
  • 127
  • 156

2 Answers2

2

It turns out that the --raw flag for git-show provides this information in a format which is easier to parse than the diff output. These lines include moved and copied files, as well.

Combining this with the --no-abbrev flag to show the full hashes and using the --format flag to hide the commit info, we get:

$ git show --raw --no-abbrev --format=
:100755 100755 0a88c4d759ce6b4f934812c85d616ff017f6caf4 633cf0a7281c549580e713edc4a0f4d0b91b3beb M      bin/quarterly-baseline
:100755 100755 e5a5a1f9437656ada68faf147393d887924bd6a7 3006514dad95f9a0249b97d984f0167c0837b61b M      bin/weekly-report
:100644 100644 82df0c621dc4f3fc98d6d4da518444d0ef3cdd9d 536eb5ad49a407660298dcf5204e3dc7ecb9aab8 M      docs/pages/api.rst
:100644 100644 267b4e017c77928e6f165095ee40043df8689da5 1d27b3084ec760870f79f434347cd2cb004dafe4 M      index.js
:100644 100644 03555ccf3978be14462b8c06a1790c9094ebbe42 846a85a5bbcf36c694d1ec244a56acd30f4494b2 R057   test/get-web-build-times-test.js        test/get-build-times-test.js
:100644 100644 d3f203c3e6d9c25df73e37ab0f3843f4c7687b1d e3c7eee94bbe379979c0c355cba86764a3f6caa9 R075   test/request-web-dev-box-stats-test.js  test/request-dev-box-stats-test.js

Each line represents a changed output file, and the hashes and filenames can be extracted with a simple regex: /:\d+ \d+ \w+ (\w+) .+ (\S+)/.

Ben Blank
  • 54,908
  • 28
  • 127
  • 156
1

The code below parses the output of git diff-tree for non-merge commits to show the hash, status (modified, added, deleted, etc.) for each file modified in a commit.

For example, in git’s history, running show-hashes 08da6496b6134 outputs

Documentation/RelNotes/2.24.0.txt M bda29d224a4f75b7497be901bd269f69d99de508

Directions for extending it include supporting merge commits and move or rename detection.

#! /usr/bin/env perl

use strict;
use warnings;
no  warnings 'exec';

my $treeish = @ARGV ? shift : "HEAD";

my $sha1 = qr/[0-9a-f]{40}/;
my $mode = qr/[0-9]{6}/;
my $file_change = qr/
  ^ :
  $mode    # mode for src; 000000 if creation or unmerged
  [ ]
  $mode    # mode for dst; 000000 if deletion or unmerged
  [ ]
  ($sha1)  # sha1 for src; 0{40} if creation or unmerged
  [ ]
  ($sha1)  # sha1 for dst; 0{40} if creation, unmerged, or "look at work tree"
  [ ]
  ([ACDMRTUX])([0-9]*)
  $
/x;

my @cmd = (qw/ git diff-tree --raw -r -z /, $treeish);
open my $fh, "-|", @cmd
  or die "$0: failed to start @cmd";

$/ = "\0";

my $commit = <$fh>;
die "$0: merge commits not supported" unless defined $commit;
chomp $commit;
die "$0: expected commit SHA1"        unless $commit =~ /^$sha1$/;

while (<$fh>) {
  chomp;

  die "$0: unexpected [$_]"
    unless my($src,$dst,$status,$score) = /$file_change/;

  chomp(my $srcpath = <$fh> || "");
  die "$0: commit=$commit, dst=$dst: missing path" if $srcpath eq "";

  print "$srcpath $status $dst\n";
}

close $fh or die "$0: @cmd failed";
Greg Bacon
  • 134,834
  • 32
  • 188
  • 245