Fri 11 Nov 2022
Better Git diff output for Ruby, Python, Elixir, Go and more
SHARE THIS POST
The regular Git users amongst you will be familiar with the diff output that breaks down into “hunks”
The first line (starting @@) is known as the hunk header, and is there to help orientate the change. It gives us the line numbers for the change (the numbers between the @@..@@), but also a textual description for the enclosing context where the change happened, in this example "class TicketPdf". Git tries to figure out this enclosing context, whether it’s a function, module or class definition. For C-like languages it’s pretty good at this. But for the Ruby example above it’s failed to show us the immediate context, which is actually a method called tickets_as_html. That’s because out of the box Git isn’t able to recognise the Ruby syntax for a method definition, which would be def ticket_as_html.
And it’s not just Ruby where Git struggles to figure out the correct enclosing context. Many other programming languages and file formats also get short-changed when it comes to the hunk header context.
Thankfully, it’s not only possible to configure a custom regex specific to your language to help Git better orient itself, there’s even a pre-defined set of patterns for many languages and formats right there in Git. All we have to do is tell Git which patterns to use for our file extensions.
Some open source projects define their own .gitattributes file. There’s one in Rails. There’s even one in the Git source that enables the diff patterns for Perl and Python.
Configure a global .gitattributes file
Instead of adding a .gitattributes file to every repo we can configure a global .gitattributes file. Just create a .gitattributes file in your home directory, fill it with all the file formats you are interested in and point Git at it.