Git diffs of LaTeX, Markdown, text, ...
Since I often edit LaTeX and Markdown files, the default style of viewing git diffs that programmers use is not really ideal for me. My diffs usually have very long lines where only a couple words changes, somewhere in the middle. Normally, when a line is changed diff displays the line twice, once for before and once for after the change (typically also distinguishing the two by colours). This, however, is not very useful when working with text and not code. You'll see two very long lines of text where you'll struggle to find what actually changed.
Luckily, git has you covered, you can use git diff
with the --word-diff
flag and then diffs don't appear as the same line repeated twice but instead the changes are displayed in place, within the line. If a segment is added then it is enclosed in {+
and +}
and shown in green and if it is deleted then it's within {-
and -}
and shown in red.
There is one caveat to this. It is crucial that you set your pager (typically less
) to break lines, otherwise you need to scroll to the right and back all the time to review the commits which is really annoying.
I knew that and so I set the following in my ~/.gitconfig
:
[core]
pager = less -FRX
To automate the process you might also want to add an alias, e.g.
alias giwd="git diff --word-diff"
to your shell config. Perfect, now you just write giwd <commit-hash>
and it shows all changes till the last commit in the --word-diff
form.
There is only one problem with this. You still need to open git log or tig, find the commit, and copy-paste the commit hash to giwd
. Imagine you do this again and again every day...
Ideally we would just run tig --word-diff
and browse the commit diffs in the --word-diff
fashion. This flag is supported in tig but there is one huge problem. The lines do not wrap in tig when --word-wrap
is used so you find yourself scrolling right and left all the time. The problems with text wrapping in tig go back to issue #2 on Github!
Luckily, tig is scriptable, so if we add
bind generic w !git show --word-diff %(commit)
bind generic W !git diff --word-diff %(commit)
in ~/.tigrc
, then upon pressing w
after selecting a commit in tig, it shows the --word-diff
of the selected commit and pressing W
shows the --word-diff
of all commits combined up until the selected one. Wonderful!
If you use Lazygit instead of tig, then you also can't show diffs with --word-diff
directly. I asked how to do this on Lazygit's slack and Luka Markušić (mark2185) found out that this is impossible to achieve thanks to the limitations of the underlying Go library that Lazygit is build on.
Luckily, as with tig, Lazygit is also scriptable. It is enough to save the following into ~/.config/lazygit/config.yml
:
customCommands:
- key: '<c-w>'
command: 'git show --word-diff {{.SelectedLocalCommit.Sha}}'
context: 'commits'
description: 'Show the commit diff with --word-diff'
subprocess: true
Then, again pressing Control-w
on a selected commit shows the --word-diff
. The key setting that makes this work is the subprocess: true
flag.
One more thing to add is that maybe you might have issues with the colours or wrapping. Then the safest way is to just replace the above command
flag with the following:
command: 'GIT_PAGER="less -R" git show --word-diff --color=always {{.SelectedLocalCommit.Sha}}'
This ensures that less -R
is used as pager and that git won't get distracted and outputs the diff in colours.
Responses (?)
JavaScript needs to be enabled to show responses. (Although, it is not necessary for posting them.)