From: Dipl. Ing. Sergey Brester Date: Mon, 21 Dec 2020 14:43:59 GMT Subject: git diff --ignore-space-change -- ignore whitespace prefers unmodified next line to modified one in patch Message-ID: <8a6a45cbda00ae1f0f679daf62fba27c@sebres.de> Steps to reproduce the issue: 1. create two simple C files and diff both ignoring whitespaces: ``` printf "if (some_var1) {\n do {\n some-code\n } while (1);\n}\n" > a.c printf "if (some_var1) {\n do {\n if (some_var2) {\n some-code\n }\n } while (1);\n}\n" > b.c git diff --ignore-space-change --no-index a.c b.c ``` which would produce fully correct resulting patch: ``` diff --git a/a.c b/b.c --- a/a.c +++ b/b.c @@ -1,5 +1,7 @@ if (some_var1) { do { + if (some_var2) { some-code + } } while (1); } ``` but this behavior will change if line 5 would be equal line 6 (containing only brace ...). 2. now we'll modify that a bit (e. g. use while instead of do, to make the lines more similar (containing only braces): ``` printf "if (some_var1) {\n while (1) {\n some-code\n }\n}\n" > a.c printf "if (some_var1) {\n while (1) {\n if (some_var2) {\n some-code\n }\n }\n}\n" > b.c git diff --ignore-space-change --no-index a.c b.c ``` which then would produce this result: ``` diff --git a/a.c b/b.c --- a/a.c +++ b/b.c @@ -1,5 +1,7 @@ if (some_var1) { while (1) { + if (some_var2) { some-code } + } } ``` As one can see, a line 6 instead of line 5 is marked as new (thereby line 6 was **completely unmodified**). In my opinion correct would be this variant (also similar patch of test in step 1): ``` diff --git a/a.c b/b.c --- a/a.c +++ b/b.c @@ -1,5 +1,7 @@ if (some_var1) { while (1) { + if (some_var2) { some-code + } } } ``` I understand that using --ignore-space-change both lines are quasi "equal", and then first "change" will be noticed as a new created line, but from point of view of the developer (and common sense) it is very strange either, especially if one considers that whole code starting from line 6 is totally unmodified. This causes that on some much complex nested blocks, this simple "first wins" logic (without a simple look-ahead), confuses still more (because affects several unmodified blocks, braces etc), especially if some conflicts should be resolved or a 3-way merge/review takes place. This makes the usage of option "--ignore-space-change" pretty pointless, because the diff of larger nested blocks is often error prune on braces, brackets etc, so the review is often needless complicated. [System Info] git version: git version 2.28.0.windows.1 cpu: x86_64 built from commit: 77982caf269b7ee713a76da2bcf260c34d3bf7a7 sizeof-long: 4 sizeof-size_t: 8 shell-path: /bin/sh uname: Windows 10.0 18363 compiler info: gnuc: 10.2 libc info: no libc information available $SHELL (typically, interactive shell): -- Regards, Sergey Brester