1

I became aware of this because a pre-commit config started checking for the trailing-whitespace condition (the generated diff in question is itself part of a repo so a git commit catches the condition of the whitespaces).

I basically refer to all the empty lines in a default git diff output which are not part of patching itself; e.g. all the empty lines before a diff --git a ... line; they always contain 1 whitespace between the 2 newlines.


I believe they are produced when it shows the surrounding relevant code which is not part of patching, for readability, but those lines in the files compared themselves do not have whitespaces!


e.g. after changing a file with contents:

hello = "Hellow Stack Overflow"

print(hello)

quit()

git diff output:

diff --git a/1.py b/1.py
index da132e0..4fdf846 100644
--- a/1.py
+++ b/1.py
@@ -1,4 +1,4 @@
-hello = "Hellow Stack Overflow"
+hello = "Hello Stack Overflow"
 
 print(hello)
 

(the line before print(hello) and the line after print(hello) in the patch have a whitespace each (and removing the whitespaces: the patch still works))

j riv
  • 3,593
  • 6
  • 39
  • 54
  • Probably "because nobody cares". But what lines are you talking about? (Show a snippet of this `git diff` output.) I've just run `git diff` in an active repository and I see no such lines before the `diff --git` lines. – torek May 12 '22 at 02:34
  • @torek I believe they are produced when it shows the surrounding relevant code which is not part of patching, for readability, but those lines in the files compared themselves do not have whitespaces! – j riv May 12 '22 at 02:36
  • 1
    Ah, you mean *context* lines. (I wouldn't count those as "before" the `diff --git ...` lines, they're "after" as part of the context.) All context lines are marked with ` ` (unchanged), `+` (added), or `-` (deleted). So a blank context line consists of one space and a newline. That's how unified diffs have always been shown and consumers of unified diffs expect this input. – torek May 12 '22 at 02:44
  • Added the example. @torek ah ok I guess it's perfectly normal. I noticed that if I remove the whitespaces with `sed`: the patch works well anyway. – j riv May 12 '22 at 02:46
  • 1
    @jriv but if there was a context line that started with a `+` or `-` and diff didn't generate context lines with a leading space, there would definitely be a problem. :) – hobbs May 12 '22 at 03:02
  • @hobbs I guess you're right, though I'm not sure why, because it appears that `git diff` sometimes turns a `+` line (in the source) to a space line (in the context) and sometimes it keeps it in the context (???). – j riv May 12 '22 at 03:09
  • I guess that in the use case of the question it's smarter to just ignore the pre-commit error by excluding the diff file in the pre-commit config. – j riv May 12 '22 at 03:26

1 Answers1

1

This is a great example. Here's the original diff again except that I've added \$ to the end of each line for visibility:1

diff --git a/1.py b/1.py\$
index da132e0..4fdf846 100644\$
--- a/1.py\$
+++ b/1.py\$
@@ -1,4 +1,4 @@\$
-hello = "Hellow Stack Overflow"\$
+hello = "Hello Stack Overflow"\$
 \$
 print(hello)\$
 \$

git diff uses a form of unified diff with context, and by default, has -U3 set: it should use "three lines of context" above and below the diff hunk's changes. Here, the change is to line 1, so there aren't three lines above to include in the first place, but there are three lines below (in fact there are four, so git diff can cut one off with -U3).

In the diff output, modified lines are prefixed with + or - to indicate an added or removed line, and an unchanged context line is prefixed with a single blank. Some naïve consumers of unified diffs could get upset if the blank before a context line is missing, so Git generates the standard form.

You can use -U0 to select no-lines-of-context, if you like. As you noted in a comment, git apply itself (and other Git-suite programs) typically don't mind if a context line loses its leading space, so you can instead strip these spaces if you want the context, but dislike the rigid format—but it's a bit tricky to know when the context ends (you must use the @@ lines to keep count, so don't use these with --recount).


1The BSD vis program does this with the -l option.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Thanks. I noticed someone commented at the OP that there are some nuances e.g. with actual `+` lines in the source that could create problems if context spaces are removed, so I guess in the original use case it's smarter to just ignore the pre-commit warning by excluding all diff files in the config. – j riv May 12 '22 at 03:24
  • 1
    You'd see a context line that starts with `+` as in the context. That doesn't *end* with a blank so it doesn't hit any of the "complain about trailing blanks" cases in some lint-checkers. But if you're trying to satisfy every lint checker everywhere, you'll eventually run into impossible cases: for instance some lint checkers say "never use a tab, ever" and others say "always compress multiple spaces into a tab when possible". – torek May 12 '22 at 03:35