> I think it could be a problem in the future if the builtin userdiff drivers started growing more invasive options, like automatically claiming to be non-binary (i.e., setting diff.cpp.binary = false by default). In other words, I think we have two options:
> 1. Builtin drivers like "cpp" can stay minimal, only setting funcname and color-words headers that aren't going to produce terrible results if we are wrong about detecting by extension.
> 2. We force the user to identify file types manually, so we can't be wrong. The "cpp" diff driver means "you are a text C file", and if a user mis-marks a binary file with that diff driver, they are the one who is wrong.
> So if it's an either/or situation, we should decide not only that extension auto-detection is a good feature, but that it trumps adding more advanced features to the builtin drivers in the future.
> Or we could decide that the extensions really are good enough, and if you really do have binary files named "foo.c", it's your problem to override the defaults with "*.c -diff".
There might be more recent discussion that I didn't find.
I rarely see files with incorrect file extensions outside of collisions and user error?
I don’t see any downside apart from extensionless files like shell scripts with the executable flag set, shebang, and no file extension which could also be solved.
Edit: and if comprehensive correctness was truly desired, file magic could make a better guess, but that would be overkill imo.
This looks like a great command line alternative to git diff or diff, but I have to admit that I greatly prefer meld when I need a quick diff against non version controlled files, or sublime merge when using revision controlled files.
I use Sublime Merge pretty much every day, and it's nothing short of fantastic.
It's properly fast, the diff/stage/commit/etc UX is excellent. I particularly enjoy how straightforward it makes it to hand-pick lines from multiple files really quickly. The interface abstracts over enough of the Git ux/api to make it get out of your way, but in a way that doesn't make what it's doing a mystery or too out of your control - hovering over a button will often yield the equivalent git cli commands for example.
Personal preference here, but it's also not an electron app, so it's very resource light.
Worth pointing out that this is not mutually exclusive with the article. You can use both, the article (when combined with this pager) will affect what appears inside the chunk header.
FWIW, it looked great on paper/Github, so I installed and tried it. The colors just overwhelmed me, so I had to uninstall it.
Thinking "perhaps, it's just the default color scheme", I installed it again and tried the `delta --show-syntax-themes` command to see the themes in action. Didn't like any of them. So uninstalled it again.
(Delta author here.) You can disable syntax highlighting, either by customizing the {plus,minus}-*-style options to not use 'syntax' as the foreground color, or by selecting the diff-highlight or diff-so-fancy emulation modes. That would allow you to still have some of the other features if they are attractive to you, such as side-by-side view, line numbers, restructuring and streamlining of the default diff format output, copyable code (no +/- characters), etc.
From the title I was hoping that it was going to do syntax-aware alignment of diffs, but alas no.
I've been using kdiff3 even though it hasn't been updated in a very long time because it has one killer feature: manual diff alignment. I can select a token in both (or all three) files and then force the diff to align at that point. It makes merges a whole lot easier. Sometimes, a single realign is all that's needed for a file merge to sort itself out. Even when that's not the case, it's easier to reason about the changes.
Did I miss something? That is, is that feature available in other diff/merge tools and I just haven't seen it?
Beyond Compare [0] has manual alignment. It works within files as well as within directories, allowing you to match up files with different names when comparing directories.
I don't think it has syntax-aware alignment, though.
In theory there's newer builds of kdiff3 but I've not had any luck running the Windows versions & I don't think there's been significant improvements to the manual alignment code which still require a lot of battling to get the right outcome.
Git looks for your personal attributes file by default in ~/.config/git/attributes (well, $XDG_CONFIG_HOME/git/attributes to be precise), so if you put it there you don't have to set the config option.
Diffs are still pretty bad at preserving context, especially the “greedy” diff algorithm that assumes that files are identical for as long as possible instead of preserving as much context around the change as possible (if the diff is equally large. This has the familiar effect where you add a method under an existing method and they both have the same documentation header prefix line such as /, then the diff will make a mess of it and not see your added method as a single chunk of text.
Instead of a regex per file type perhaps a better diff tool could actually diff the parsed code (if possible) and produce a more sensible diff and context?
Though, being able to refactor code, and assert that it is logically and functionally equivalent as the previous checkin would be super useful, even if there’s some gaps (sting value or comparison changes could not be asserted, for example)
This makes your git diff highlight the actual different characters between two lines, makes file names easy to see (and easy to copy, due to no a/ b/), makes renames and blank lines clear and readable.
It is so nice to get all this without a separate GUI diff visualiser when doing anything git-related from the command line.
Wow this is insanity. I thought these would all be the default. I recently introduced .gitattributes into our work codebase, but that was to improve GitHub's ability to hide generated files from PRs:
A bigger problem is tree structures, it is particularly egregious for HTML and JSON where the output tend to be a complete mess of red and green. I think a good solution would be for git to call out to the respective language servers (the VS Language Server Protocol) and render changes based on AST and syntax specific diffs.
This is hugely helpful. I always have trouble scanning the git diffs because the first line of each hunk is often the same, causing me to take longer to parse the context.
This should speed up my adds, and cut down on accidental stagings.
I’ve been using git since a year or two after it was released and I’ve never paid any attention to that part of the diff. I could see it that preventing some editing of the wrong method but that is something testing should reveal.
I’m curious if others see some value in it, either before or with changes from this post?
Ah, thanks. I scanned those so many times but I never caught it. I think I'm used to not reading the header because, as this points out, it isn't always useful.
I use these a lot when someone sends a patch, I'll use `vim -t <function>` to jump to the definition of <function> to better understand the change. (Where <function> is from the header of the hunk.)
In the first diff after the @@ there's a reference to the enclosing class, in the second diff it's a reference to the enclosing method.
Which could help perhaps if the methods are moved?
Is there a good utility for diff-ing JSON content? I am calling jq to sort keys first and then let the default textual diff highlight the changes, but that's neither convenient nor complete.
Graphtage is a command line utility and underlying library for semantically comparing and merging tree-like structures such as JSON, JSON5, XML, HTML, YAML, and TOML files.
speaking of git tricks. `git grep` can take a file pattern and will only search in files matching that pattern, and it's way faster than grep -R -- about on par with `ag`, the SilverSearcher.
I've been using git forever, and never even noticed that hunks get a class identifier. I pretty much have only been diffing Python. I guess it's so useless I never even noticed!
I found a 2011 patch/proposal to make it the default, which appears to have stranded: https://lore.kernel.org/git/20110825204047.GA9948@sigill.int...
With some discussion by the patch's author of possible downsides (https://lore.kernel.org/git/20110826025913.GC17625@sigill.in...):
> I think it could be a problem in the future if the builtin userdiff drivers started growing more invasive options, like automatically claiming to be non-binary (i.e., setting diff.cpp.binary = false by default). In other words, I think we have two options:
> 1. Builtin drivers like "cpp" can stay minimal, only setting funcname and color-words headers that aren't going to produce terrible results if we are wrong about detecting by extension.
> 2. We force the user to identify file types manually, so we can't be wrong. The "cpp" diff driver means "you are a text C file", and if a user mis-marks a binary file with that diff driver, they are the one who is wrong.
> So if it's an either/or situation, we should decide not only that extension auto-detection is a good feature, but that it trumps adding more advanced features to the builtin drivers in the future.
> Or we could decide that the extensions really are good enough, and if you really do have binary files named "foo.c", it's your problem to override the defaults with "*.c -diff".
There might be more recent discussion that I didn't find.