WinMerge - ignore all whitespace including newlines and formatting changes
Asked Answered
S

4

17

How can I ignore "code style" changes while using WinMerge as a difftool? Specifically across two commits.

So that

thing
{
  a,
  b
}

and

thing { a, b }

would be treated as identical.

Essentially this question, but for winmerge rather than diff.

.gitconfig:

[diff]
    tool = winmerge
[difftool]
    prompt = false
[difftool "winmerge"]
    cmd = "$HOME/scripts/winmerge.sh" "$LOCAL" "$REMOTE"
[mergetool]
    prompt = false
    keepBackup = false
    keepTemporaries = false
[merge]
    tool = winmerge
[mergetool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e -u -fm -dl \"Local\" -dr \"Remote\" "$LOCAL" "$MERGED" "$REMOTE"

(winmerge.sh just calls WinMergeU.exe -e -u -wr "$1" "$2")

None of the command line options seem to fit, and I think line filters won't work because they are per-line.

Swellfish answered 9/7, 2020 at 23:7 Comment(3)
Diff tools are traditionally line-based as programs are written as text in lines. You're basically asking for a diff at the tokenized & normalized level, not at the textual level. See here, but it's not directly usable answer, just an explanation of the conceptual and practical problem.Osana
@Osana yes, and JD Frias's answer gets closest to that idea. My "solution" since I asked this question has been to enforce clang-format rules in my team :). I could envision a theoretical tool which runs a formatter but keeps track of the original source locations, and then does a diff on the formatted text but shows the user the source-mapped originals for editing. Similar to how you can debug transpiled javascript by stepping through the typescript. I'm not sure that tool exists currently, as you said.Swellfish
Coming back to this two years later: There is no option in WinMerge to do this. I have found difftastic to do what I was actually asking here, which is syntax-tree-based diffs. It does so at the cost of speed and memory, so I end up having both winmerge and difftastic in my gitconfig and switch between them depending on my needs. For my given example (with .cpp extensions), difftastic prints "No syntactic changes".Swellfish
S
1

To answer my own question with the benefit of more time:

  • This is not possible with WinMerge
  • difftastic does this for read-only diffs at the cost of speed and memory
  • No tool that I'm aware of does writable diffs (e.g. conflict resolution) while showing semantic-based diffs

Not-quite-there solutions:

Ignore blank lines; Ignore carriage return differences (Windows/Unix/Mac)

This ignores line feed differences, and full blank line differences, but does not compare files semantically. It does help in certain simple cases.

Line filter ^\s*$

Same as "Ignore blank lines"

.gitattributes formatter with textconv for specific file types

This is the closest option for read-only diffs, with the downsides of:

  • needing to define a separate attribute (and formatter) for each file type
  • displaying the formatted versions of the files rather than the original

My current solution

  • For conflict resolution, use WinMerge as-is with as much of the "ignore" options turned on as possible. Resolving conflicts with formatting changes is a massive pain no matter what you do, so try to isolate formatting changes to their own merges.
  • For diff viewing, use difftastic which uses tree-sitter to compare code on an AST level rather than a textual level
  • When difftastic is slow or hogging memory, fall back to diff/WinMerge/VSCode
Swellfish answered 28/2 at 19:40 Comment(0)
C
20

This option works for me:

WinMerge -> Edit -> Options -> Compare -> General: Ignore blank lines; Ignore carriage return differences (Windows/Unix/Mac)

etc.

The answer was taken from https://superuser.com/questions/174275/can-i-compare-only-file-contents

Crossed answered 14/2, 2021 at 22:53 Comment(2)
This doesn't do it if you have one file with some blank lines inserted and the other one doesn't AND there are character-level differences between the non-blank lines. In that case, "Align similar lines" is needed. And these other options seem redundant to that one (except the line conversion probably).Diphthong
The question is how to do get the identitcal diff result when comparing the same text where in one file it is in a long line and in the other with separated line (to fit a column length for example).Obsess
S
1

To answer my own question with the benefit of more time:

  • This is not possible with WinMerge
  • difftastic does this for read-only diffs at the cost of speed and memory
  • No tool that I'm aware of does writable diffs (e.g. conflict resolution) while showing semantic-based diffs

Not-quite-there solutions:

Ignore blank lines; Ignore carriage return differences (Windows/Unix/Mac)

This ignores line feed differences, and full blank line differences, but does not compare files semantically. It does help in certain simple cases.

Line filter ^\s*$

Same as "Ignore blank lines"

.gitattributes formatter with textconv for specific file types

This is the closest option for read-only diffs, with the downsides of:

  • needing to define a separate attribute (and formatter) for each file type
  • displaying the formatted versions of the files rather than the original

My current solution

  • For conflict resolution, use WinMerge as-is with as much of the "ignore" options turned on as possible. Resolving conflicts with formatting changes is a massive pain no matter what you do, so try to isolate formatting changes to their own merges.
  • For diff viewing, use difftastic which uses tree-sitter to compare code on an AST level rather than a textual level
  • When difftastic is slow or hogging memory, fall back to diff/WinMerge/VSCode
Swellfish answered 28/2 at 19:40 Comment(0)
M
0

You could add a .gitattributes for your file. This would run a tool to normalize/beautify/prettify both files before comparison.

This will run .json files through json_pp before compare:

echo "*.json diff=json" >> .gitattributes
git config diff.json.textconv json_pp

Check out git documentation for details: https://git-scm.com/docs/gitattributes

Source: https://t-a-w.blogspot.com/2016/05/sensible-git-diff-for-json-files.html

Modality answered 9/7, 2020 at 23:45 Comment(2)
This definitely does work to show semantic diffs, but I would still rather a winmerge-specific option that still shows the original files, but doesn't highlight the code style differences. Running a formatter can get a little slow for larger cpp files, and I'm also worried about the issues it could cause when editing diffs and saving them. I don't want to accidentally commit formatting changes if I don't need to.Swellfish
I use Beyond Compare has custom rules for comparison, and tons of other features. It is paid though, well wroth it in my opinion #notsponsoredModality
A
0

In addition of ignoring white spaces/blank lines/...etc. Do the following

  • Go to Tools->Filter
  • Select "Linefilters" tab
  • Check Enable Line Filters
  • Add the following expr, and make sure it is checked ^\s*$

enter image description here

-Refresh the comparison

Acerbate answered 14/9, 2023 at 20:13 Comment(1)
Thanks for your answer, but this will just filter out blank lines, which is not what I'm asking. I wanted the behavior of difftastic, which does AST-based semantic diffs. I use that tool now if I need that, and winmerge when I don't.Swellfish

© 2022 - 2024 — McMap. All rights reserved.