0

Could not find a difference filtering certain file types? I just want to compare .js files for example between branch a and b?

bier hier
  • 20,970
  • 42
  • 97
  • 166

1 Answers1

4

Does this simply work?

git diff branch-a branch-b -- '*.js'

If you want to have a more complete view:

git diff branch-a branch-b -- $(cat <(git ls-tree --name-only -r branch-a) <(git ls-tree --name-only -r branch-b) | sort | uniq | grep '\.js$')

What does this super-long command do?

This part should be obvious, the -- at the end of this part means all subsequent arguments are file paths, not options

git diff branch-a branch-b --

Let's take a look at this giant command:

$(cat <(git ls-tree --name-only -r branch-a) <(git ls-tree --name-only -r branch-b) | sort | uniq | grep '\.js$')

The first thing is this:

cat <(git ls-tree --name-only -r branch-a) <(git ls-tree --name-only -r branch-b)

This uses git ls-tree to list all files in commits, and use cat to collect the output of files in the two branches. <() is a shell substitution, which is replaced by the name of a pipe. The other side of the pipe is apparently the output of git ls-tree.

| sort | uniq | grep '\.js$'

Sort and filter the combined files - in practice there are likely may duplicates, so uniq takes duplicated stuff out. grep '\.js$' at the end filters to show only files whose path ends in .js.

The result of the long command in $() is the combined .js files in both branches, which is then passed to git diff to filter diff files. This is exactly what you want, if I correctly understand.


What about packing this into a convenient shell script for later use?

#!/bin/sh
SOURCE=${1:-master}
TARGET=${2:-HEAD}
FILTER=${3:-.*}
exec git diff $SOURCE $TARGET -- $(cat <(git ls-tree --name-only -r $SOURCE) <(git ls-tree --name-only -r $TARGET) | sort | uniq | grep "$FILTER")

Usage:

./diff-all.sh branch-a branch-b '\.js$'
iBug
  • 35,554
  • 7
  • 89
  • 134
  • Actually, you can just quote the `*.js` part to get Git to do the same thing: `git diff branch-a branch-b -- '*.js'`. The arguments after `--` are pathspec arguments, which can be more than just file names. You just need to be sure the shell doesn't eat the `*` by expanding `*.js` to all the top level `*.js` files, before Git gets hold of it. – torek Dec 18 '18 at 06:08
  • @torek I should have remembered that. Thanks for the heads up. – iBug Dec 18 '18 at 06:10
  • @iBug Good one, how can I do this for multiple file types filter, something like this `git diff branch-a branch-b -- $(cat <(git ls-tree --name-only -r branch-a) <(git ls-tree --name-only -r branch-b) | sort | uniq | grep '(\.js|\.vue|\.php)$')` is possible ? – Vicky Dev Sep 01 '22 at 15:07