skip navigation

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:

        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:

  - 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.)

Indieweb interactions: Like/Reshare/Reply/Bookmark with Quill or Like/Reshare/Reply/Bookmark with Micropublish.