Hide unchanged lines when using git word-diff

Viewed 407

I have two files, old.txt:

Line 1
Line 2
Line 3
Line4
Line5
Line 7
Line 7
Line 8

and new.txt:

Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8

If I run git diff --no-index --word-diff-regex=. old.txt new.txt then it shows that the only changes are whitespace fixes on lines 4 and 5 and fixing the wrong number on line 6:

diff --git a/old.txt b/new.txt
index be8495f..a982fdc 100644
--- a/old.txt
+++ b/new.txt
@@ -1,8 +1,8 @@
Line 1
Line 2
Line 3
Line{+ +}4
Line{+ +}5
Line [-7-]{+6+}
Line 7
Line 8

It unfortunately also shows the unchanged lines (1 to 3, 7 and 8), but this can be fixed by removing context lines with --unified=0, e.g. git diff --no-index --unified=0 --word-diff-regex=. old.txt new.txt:

diff --git a/old.txt b/new.txt
index be8495f..a982fdc 100644
--- a/old.txt
+++ b/new.txt
@@ -4,3 +4,3 @@ Line 3
Line{+ +}4
Line{+ +}5
Line [-7-]{+6+}

However, in the case where the word-diff regex has been customised to ignore whitespace differences, e.g. git diff --no-index --unified=0 --word-diff-regex="[^[:space:]]" old.txt new.txt, it shows:

diff --git a/old.txt b/new.txt
index be8495f..a982fdc 100644
--- a/old.txt
+++ b/new.txt
@@ -4,3 +4,3 @@ Line 3
Line 4
Line 5
Line [-7-]{+6+}

Note that line 4 and 5 now show no changes, yet still appear in the output. This probably happens because unlike lines 1 to 3 those lines aren't fully identical.

However is there a git option to not show lines when they are unchanged according to the word-diff-regex?

2 Answers

There is no such option, but probably there should be. As you surmised, Git is really doing line-by-line diffs, then superimposing word-to-word edit directives on the result. When the word definition results in "no change", you get what you saw.

(Alternatively, word-diff could use words as the actual symbols fed to the internal diff engine. But this results in much bigger inputs and the Myers algorithm is O(ND), so with N and D both increasing, this would use much more time.)

In the end I used grep to only show lines with changes by looking for {+ and [- using the expression grep -E "\{\+|\[-", e.g.

git diff --no-index --unified=0 --word-diff-regex="[^[:space:]]" old.txt new.txt | grep -E "\{\+|\[-"

which outputs:

Line [-7-]{+6+}

This wouldn't give a valid patch file as output, but it worked well enough for me such that I could visually compare the changes between some large files.

Related