Create Git diffs with proper function context

Thu, 2016-02-11 13:37 -- drunken monkey

TL; DR

For years I have been annoyed (slightly, but still) that Git diffs for PHP classes always just contained the class header instead of the method header as the function context. I finally got round to doing a bit of research and it turns out that the solution is astonishingly easy: just one small and simple config file and it will magically work.

The problem

You might have noticed it, and maybe been annoyed by it, too: when you create a diff file with Git and have changes inside PHP class files, you get hunks that look like the following:

@@ -40,6 +40,7 @@ class SearchApiViewsHandlerFilter extends views_handler_filter {
       '<=' => t('Is less than or equal to'),
       '=' => t('Is equal to'),
       '<>' => t('Is not equal to'),
+      '!=' => t('Is REALLY not equal to'),
       '>=' => t('Is greater than or equal to'),
       '>' => t('Is greater than'),
       'empty' => t('Is empty'),

So, where you would normally expect the function context, to quickly get an idea what that change means, the diff instead just contains the class name, which is much less helpful (especially if the file name already tells you the class).

Well, after years of being regularly (slightly) annoyed by this (more so in recent years, with the OOP shift in Drupal 8), I finally searched this new place called "the interwebs" and arrived at the very simple solution.

The solution

It turns out Git's diff functionality already has support for creating the right function context information for various file types – it just doesn't know which files correspond to which file type. (It seems not even the standard .php extension is recognized by default.)

To remedy this, simply create a file with the following contents:

*.engine   diff=php
*.inc      diff=php
*.install  diff=php
*.module   diff=php
*.php      diff=php
*.profile  diff=php
*.test     diff=php
*.theme    diff=php

Save the file either in .git/info/attributes or .gitattributes (for just the local project), or (to change this globally) in $HOME/.config/git/attributes (or $XDG_CONFIG_HOME/git/attributes, if that variable is set). That's it – testing again, we now see the proper function context in the diff:

@@ -40,6 +40,7 @@ public function operator_options() {
       '<=' => t('Is less than or equal to'),
       '=' => t('Is equal to'),
       '<>' => t('Is not equal to'),
+      '!=' => t('Is REALLY not equal to'),
       '>=' => t('Is greater than or equal to'),
       '>' => t('Is greater than'),
       'empty' => t('Is empty'),

Much better, right?

Note: I haven't yet found out where to put the global attributes file for Windows. If you know, please post a comment and tell me, and I'll include it here.

Background information

For more information on Git attributes, please see the documentation. I didn't know about this at all before, but it seems there's actually a lot you can configure per file type, so there might be other very practical tips for customization.
If you find or know of any, please post them so others can profit from them, too – just as I hope this post was useful to at least a few of you!

As an afterthought, I've also added this tip to the Git documentation in Drupal.org's handbook. Hopefully, more people will find it that way.

Comments

Submitted by drunken monkey on

Thanks for your input!
However, your link only talks about Git config, Git attributes is a different file and, at least on Linux, the location is derived differently. It looks like it might be %HOME%\.config\git\attributes, even though that looks really weird – in any case, I'd need someone with Git installed under Windows to verify this.

Submitted by drunken monkey on

You're right, that does make a lot of sense.
Thanks for creating the issue, let's see how it turns out!

Edit: Seems other people agree – this was already added to Drupal Core, I just didn't know it. So, the tips in this post will only help for contrib patches, for Core it should already work as expected.

Submitted by Anonymous (not verified) on

nice

Add new comment

To prevent spam, submitting full URLs in comments is not allowed. Please omit the "http[s]://" portion of the URL and I will restore the complete URL on review.

Filtered HTML

  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <q> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <sup> <sub> <p> <br>
  • To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.