If you've been working with Backdrop for a while, you'll notice that sometimes, a particular module, theme, layout template (or sometimes even Backdrop core) doesn't quite work right - or - perhaps it just doesn't quite work the way you'd like it to for your particular project.

Fortunately, this is the world of open-source, and you are most likely not the first person to have this concern. Your first line of attack should always be to search the issue queue for the project and see if someone else has already fixed this problem for you (or added the new feature). Quite often, you'll find that they have, and there will be a Pull Request (PR) linked from the issue containing the necessary changes to the code.

Once an issue has a PR on GitHub, it's easy to create a patch for your own site by adding .patch to the end of the URL.

The PR you find can be in one of many various states, my favorite is when it's already gone through the approval process, been merged into the project, and is already included in a stable release. At this point all you need to do to get the solution on your own website is to upgrade to the version that includes the change. This just means updating to the latest stable release. YAY!

Sometimes the solution has been merged into the project, but it's not yet included in a stable release. In this case you will need to update to the development version of the project and do some thorough testing either on a local copy of your website, or someplace safe like a a 'dev' environment where it will be okay if your site explodes. (Never upgrade to a dev release on a production website without testing first!)

If the PR for the fix/feature hasn't yet been committed to the project, you're going to need to apply the patch yourself. (See my tech tip on applying patches.) And if the patch adequately adds your fix/feature, you will need to learn how to maintain a sustainable development workflow that includes care for this patch.

Here's what I do:

For every Backdrop project, I create a file named PATCHES.txt that lives just outside my web root. This file includes a list of all patches currently applied to the project - for both core and contrib. It includes what was patched, why it needed to be patched, a link to the issue where the work is being done, and sometimes also a link to the Pull Request where work is being done.

Here's a real-world example from one of my Backdrop sites:

#
# PATCHES applied to this project
#

--------------------------------------------------------------------------------

## Core

Upgrade layouts -- use settings from settings.php
  https://github.com/backdrop/backdrop-issues/issues/5289
  https://github.com/backdrop/backdrop/pull/3787.patch

--------------------------------------------------------------------------------

## Contributed modules

blockreference - fix entity access problem
  https://github.com/backdrop-contrib/blockreference/issues/9
  https://github.com/backdrop-contrib/blockreference/pull/11.patch

bueditor - prevent php notice in upgrade from D7
  https://github.com/backdrop-contrib/bueditor/issues/16
  https://github.com/backdrop-contrib/bueditor/pull/17.patch

easy social - restore option list (prevent php warning)
  https://github.com/backdrop-contrib/easy_social/issues/1
  (committed to -dev)

markdown - prevent curly braces deprecated in require_once
  https://github.com/backdrop-contrib/markdown/issues/4
  https://github.com/backdrop-contrib/markdown/pull/7.patch

reference - add a UI for converting fields
  https://github.com/backdrop-contrib/reference/issues/28
  https://github.com/backdrop-contrib/reference/pull/70.patch

xmlsitemap - prevent php warning in upgrade from D7
  https://github.com/backdrop-contrib/xmlsitemap/issues/101
  https://github.com/backdrop-contrib/xmlsitemap/pull/102.patch

There are two main reasons to manage a list like this. The first one is that it will assure you are searching the issue queue for solutions for problems rather than doing it on your own (this will save you time in the long run, learn to use Open-Source to your advantage!). The second reason is that this simple file will also save you time (and sanity) during future updates.

For example: If a new version of XMLsitemap module comes out, my site will alert me that I need to update. I can check this file to see if I am maintaining any patches against XMLsitemap, and if I am, the first thing I should do is visit the URL for the issue I have included in this file. From there I will review the status of the current Pull Request:

  • The Pull Request has been merged, and is included in the new version. (In this case I can delete the three lines related to this patch from my PATCHES.txt file.)
  • The Pull Request has been merged, but it's not in the latest release (it's still in the dev version): In this case I need to test the dev version of the module and make sure it's safe to run on my website before I deploy it. (In this case, I will remove the link to the PR, and add some text like "committed to -dev" instead.)
  • The Pull Request has not been merged yet: In this case I will read any comments that have been added to the queue since I was last here, and find out why the patch was not incorporated. Did someone else find a problem with the approach taken in the patch? Is there a new Pull Request? If there is a new Pull Request I will try that one instead, and update the link in the PATCHES.txt file to point to the new comment where the latest (working) patch was submitted.
  • No one has looked at this issue for a while. If this is the case, I try to apply the previous solution, and I also usually add a polite comment to the bottom of the issue saying something like "PR still works for me on 1.x-1.2.0!" Or, if it doesn't still work, you can say what happened instead.

By reading the list of possible statuses of the issue above, it should be clear why it's not a good idea to simply include patch files in your version control system, and try to blindly re-apply the same patches after updating your code. (Something I've heard other developers mention they do.)

  1. The solution might have been committed already
  2. There might be something wrong with the old solution
  3. The old solution might have become obsolete

If any of the three above situations crop up, you'll wish you had a link to the issue handy so that you can find out what happened.

Why not start there and save yourself the trouble? :)