Skip to main content

Introduction to Drupal Patch Files

I recently joined PreviousNext and was soon getting acquainted with contributing to Drupal core and contrib projects. A big part of the contribution workflow is working with patch files in the issue queue, so I wrote this post to help anyone who wants to know about patching in Drupal.

by pasan.gamage /

What is a patch file

A patch file is basically a text file having a .patch extension which includes a formatted set of code in particular language extracted using git diff. The usage of a patch file in drupal is to make anyt code change such as fixing bugs, improving performance issues, or adding new features.

How to apply a patch file

The first thing you'll want to do when working with the Drupal issue queues, is to apply a patch provided by another developer to test it out locally.

There are several ways to apply a patch file. But before you do, it is important to know the directory you are currently in. Usually patch files are created relative to the project root directory. In other words it could be Drupal root directory itself or a contrib module directory.

  • In a scenario where you want to patch a Drupal code you should navigate to the Drupal directory using cd command from your terminal.

  • If you want to patch a contrib module or a theme, you have to navigate to that particular directory. Once confirming the directory is correct; ( you may use pwd in mac ) issue below chosen commands.

To apply the patch you need to have the patch file present in your project. To do so, navigate to the directory and download the patch file directly from terminal using curl or wget

Downloading patch file

  • Using curl

curl -O<https://www.drupal.org/XXXX.patch>

  • Using wget

wget -O<https://www.drupal.org/XXXX.patch>

Applying a patch

There are several commands that can be used to patch. And depending on the situation you can choose which to use.

  • When patching a files that are in git repository;

git apply<option> <path/file.patch>

e.g:  git apply -v --index <path/file.patch>

Commonly used options
  • -v

Report progress to stderr. By default, only a message about the current patch being applied will be printed. This option will cause additional information to be reported.

  • --index

The patch is also applied to the index, which helps to track modified files.

  • -3

When the patch does not apply cleanly, fall back on 3-way merge

e.g:  git apply -v -3use_form_element_of-2648950-118.patch
 

  • When patching files in a non git environment;

patch -p1 <path/file.patch

  • -p option tells patch how many leading path prefixes to strip.

e.g: -p1 will strip /core directory

/core/lib/Drupal/Core/Path/CurrentPathStack.php

  • -p1 is normally the right option, and is the default for git apply.
  • If patching fails, you can try -p0 instead.

 

  • If the patch file in the same directory where the file to be patched is present, simply run

patch < file.patch

Reversing patches

If you get stuck you can undo applying the patch. Depending on the exact command you used to patch, you can use the same command, with an extra argument, to reverse the applied patch from code base.

e.g:    patch -p1 -R <path/file.patch     (if applied with -p0 use the same again)

git apply -Rpath/file.patch
 

When to reverse a patch

Based on the reason the patching was performed, unpatching can be carried out.

  • After performing testing to a particular patch.

  • If the patch has introduced code break.

  • When updating to a version of the same patch

 

Understanding patch file syntax

It is important to understand the format of the patch file that is being used. It will help you to determine which file(s) will be modified and it will be easy to track whether the changes were applied to correct files by running git status command.

Below is an example patch file.

diff --git a/core/lib/Drupal/Core/Path/CurrentPathStack.php b/core/lib/Drupal/Core/Path/CurrentPathStack.php
index cb7878650f..51b97cd71e 100644
--- a/core/lib/Drupal/Core/Path/CurrentPathStack.php
+++ b/core/lib/Drupal/Core/Path/CurrentPathStack.php
@@ -1,6 +1,8 @@
<?php

namespace Drupal\Core\Path;
+
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

/**
@@ -46,7 +48,7 @@ public function __construct(RequestStack $request_stack) {
   * @return string
   *   Returns the path, without leading slashes.
   */
-  public function getPath($request = NULL) {
+  public function getPath(Request $request = NULL) {
    if (!isset($request)) {
      $request = $this->requestStack->getCurrentRequest();
    }
@@ -67,7 +69,7 @@ public function getPath($request = NULL) {
   *
   * @return $this
   */
-  public function setPath($path, $request = NULL) {
+  public function setPath($path, Request $request = NULL) {
    if (!isset($request)) {
      $request = $this->requestStack->getCurrentRequest();
    }

There are common sections for all the patch files which conveys information like;

  1. Which files have been modified and that diff is in the "git" diff format.

    • diff --git a/core/lib/Drupal/Core/Path/CurrentPathStack.php b/core/lib/Drupal/Core/Path/CurrentPathStack.php

  2. diff header of the git repository

    • index cb7878650f..51b97cd71e 100644

  3. unified diff header

    • --- a/core/lib/Drupal/Core/Path/CurrentPathStack.php
      +++ b/core/lib/Drupal/Core/Path/CurrentPathStack.php

  4. one or more hunks of differences

  • @@ symbol is used to show hunk area
  • @@ from-file-range to-file-range @@

    • e.g: @@ -67,7 +69,7 @@

  • @@ -<start line>,<number of lines>

    • e.g: @@ -67,7

  • '+' and '-' to show line has been added or if line has been removed

    • +use Symfony\Component\HttpFoundation\Request;

    • -  public function getPath($request = NULL) {

I hope that helps provide an introduction on how to use patches for Drupal core and contrib development.

Further Reading