I'm trying to use git's --ignore-matching-lines
, but running into some weird behavior. Here's the output of a plain git diff
:
$ git diff test.txt
diff --git a/test.txt b/test.txt
index 602c47d1cb..82655814c5 100644
--- a/test.txt
b/test.txt
@@ -1,5 1,7 @@
-Hello world
Hello whitespace world
Lots of blank lines
Goodbye world
However, if I run
$ git diff --ignore-matching-lines='^$' test.txt
I get no output
Why is this ignoring the change that adds the word whitespace
?
CodePudding user response:
This could be caused by how '$
' itself is interpreted, as detailed in "How does git diff --ignore-matching-lines
work", by Sjoerd Langkemper (also a Stack Overflow user):
Git runs each regex over each line.
These lines end in a newline, so our regex is actually checked against:His bill will hold more than his belican,\n
Where
\n
stands for a newline character.When we have a change that adds an empty line, the regex is ran against a single byte string consisting of
\n
.
How do we match that?It’s easier to use something like
--ignore-blank-lines
to ignore blank lines.
(Check, by the way, if git diff --ignore-blank-line
is a good option in your particular case)
However, this does not work well together with other regular expressions that we want to ignore.
If we want to ignore a change that performs both an uninteresting belly-related change and adds an uninteresting empty line, our regular expressions we give to-I
need to match both for the change to be hidden.
So we need a regular expression that matches an empty line, and--ignore-blank-lines
and other white space related options don’t change that.An empty line cannot be matched with
^$
.
^
matches both the beginning of the line and the beginning of the buffer.- Similarly,
$
matches both the end of the line as the end of the buffer.All changed lines end in a newline, just before the end of the buffer.
This means that^$
matches every changed line.
The newline at the end starts a new line, and is immediately followed by the end of the buffer.… his belican,\n ↑ ^ matches because \n starts a new line $ matches because the buffer ends here
That would explain why a --ignore-matching-lines='^$'
is ignoring the change that adds the word whitespace
: it is ignoring all the lines!
To match more precisely, we can use
\`
to match the start of the buffer, and\'
to match the end of the buffer.
An empty line can thus be matched with:\`\n\'
Where
\n
is an actual newline, notbackslash-n
.
This needs much escaping to enter correctly in a shell:git diff -I $'\\`\n\\\'' …