Nguyen Thai Ngoc Duy [off-list ref] writes:
That may explain it. "git diff <ref>" walks through the index, unpacks
tree objects along the way, matches up entries with the same path from
the branch, the index then feeds matching entries to diff function.
Yeah, that would explain it. The implementation of diff-index has changed
a few times and the latest incarnation is based on unpack-trees, _merging_
the tree and the index, introduced by d1f2d7e (Make run_diff_index() use
unpack_trees(), not read_tree(), 2008-01-19).
Of course the merge machinery does not know anything about pruning with
pathspec, so it is understandable (not justifiable) it would walk the full
tree.
Will try to find time this week to cook up something.