Making a patch

Last updated on
1 December 2022

Short URL to this page: drupal.org/patch/create

Video

There is a short video on Applying and Creating Patches with Git that covers much of the material on this page.

Introduction

Previously, the main way to contribute source code changes to a Drupal project repository was via patch files, as described on this and other pages in this section. As of November 2020, we have a different workflow available, similar to what open-source contributors commonly use on sites like GitHub, using issue forks and merge requests. You can still use the patch workflow described here, but for larger changes, or issues where many people are collaborating on the changes, it is preferred to use the fork/merge workflow instead.

For smaller changes, this page outlines a workflow for making a patch in a local workspace, based on local "feature branches". This page assumes you have already set up Git. Note that you can also use the drupalorg-cli tool to create an issue branch.

Prepare the local repository

  1. Follow the steps on Cloning a Drupal git repository to make a local copy of the repository or update your existing local copy to the latest version.
  2. Create a local "feature branch" for the issue you're working on.
    git checkout -b [issue-number]-[short-description] # e.g. 123456-some-bug
    
  3. If there was a previous patch that you are using as a starting point, follow the steps in Applying a patch to apply the previous patch.

Make the patch

  1. Make the changes you want to the repository you are working on.
  2. When you're ready to make a patch, open a terminal window and change to the repository directory.
  3. If you have added any new files, be sure to add these before committing: git add new.filename. Then commit any changes you've made to your local feature branch: git commit -m "my new feature"
  4. If there is a long lag between when you most recently cloned or updated the repository, and when you are finished making your changes, you will want to rebase your patch so that it will apply to the most recent updates to the repository. To do this, run these commands:
    git fetch origin
    git rebase origin/BASE_VERSION

    where BASE_VERSION is the branch you started from, such as 8.9.x or 7.x-2.x.
  5. Use the git diff origin/BASE_VERSION command to review the changes that will go into the patch, where BASE_VERSION is the branch you started from, such as 8.9.x or 7.x-2.x. Also review git status to make sure that all the changes you made are committed.
  6. Check locally that the changes pass the pre-commit checks, following the steps in running core development checks.
  7. When you're ready, create the patch with this command:
    git diff origin/BASE_VERSION > PATCH_FILE_NAME.patch
    See Patch guidelines for suggestions on naming patch files. If your patch removes a binary file, you'll need to add --binary in the command:
    git diff --binary BASE_VERSION > PATCH_FILE_NAME.patch
  8. Upload the patch to the issue, along with an interdiff file (if there was a previous patch) and a comment explaining your changes. Set the issue status to Needs review. The automated tests will run, if the project maintainer has set up automated testing for patches on this branch of the project.

When you're done: Code cleanup

After you have finished testing the patch, you'll want to get your repository back to a "clean" state:

  • Use this command to revert one file that has not been committed: git checkout filename.file
  • Use this command to revert all files that have not been committed: git reset --hard
  • Use this command to delete the feature branch you created: git branch -D [branch-name]

Making Updates To Composer-based Core Dependencies

Some core contributions will modify the Composer-based dependencies. This can lead to some confusion as to how to generate the proper composer.lock file. Here’s what you need to know for making changes to Drupal core 8.8 and later:

Composer allows you to pretend you’re on a core branch, despite being on a feature branch. An example might be that you’re contributing to Drupal 9.0.x, but you have checked out a feature branch such as 3091418-update-things. This feature branch might change the root composer.json, and it might change core/composer.json.

You might be tempted to just type composer update and be done. However, Composer will complain that it can’t find a version of drupal/core for 3091418-update-things-dev. That is as it should be, because there is no such version of Drupal core, and your patch wouldn’t work in DrupalCI anyway.

What you should do instead is a command like this:

COMPOSER_ROOT_VERSION=9.0.x-dev composer update [list of packages you updated]

If your changes include modifying core/composer.json, you should add drupal/core to the list, like this:

COMPOSER_ROOT_VERSION=9.0.x-dev composer update drupal/core [list of other packages you updated]

Here’s how that’s constructed:

  • COMPOSER_ROOT_VERSION tells Composer what version to try to resolve for all the updates you specify.
  • 9.0.x-dev is a concatenation of the version branch of core we’re working on (9.0.x) and -dev. So if your issue is targeted to 8.9.x, the value would be 8.9.x-dev, and so forth.
  • composer update tells composer to update stuff.
  • *Only update the dependencies you changed. If you made changes to drupal/core, you should include that package in the list. Generally, we want to minimize changes to the composer.lock file, so only update the dependencies you changed.

This will make Composer update the dependencies themselves, and also the composer.lock file to include all the things you changed.

Additional notes

When you run composer update on drupal/drupal, there’s an event script which will look at the composer.lock file and generate some metapackages.

These metapackages are located at composer/Metapackage/. They will eventually become Composer packages, and will be available to everyone as drupal/core-recommended, drupal/core-dev, and drupal/core-dev-pinned.

This means that if your change to any Composer dependencies modifies anything in the composer/Metapackage/ directory, then you should include that in your patch.

Here is a sample workflow for this sort of Composer update:

# Start clean.
git checkout 9.0.x
git pull origin 9.0.x
rm -rf vendor/
composer install
# Start working on our feature branch.
git checkout -b feature-branch
# Manually edit core/composer.json and save the file.
# We updated psr/log from ^1.0 to ^1.1.
COMPOSER_ROOT_VERSION=9.0.x-dev composer update drupal/core psr/log
# Composer tells us that we updated psr/log from 1.1.0 to 1.1.2.
git diff —name-only
# Show us this:
#  composer.lock
#  composer/Metapackage/CoreRecommended/composer.json
#  core/composer.json
# We must add all those files to our changes, even if we didn't
# directly touch the metapackages.
git add composer.lock core/composer.json composer/Metapackage/
git commit -m 'Updated psr/log'
git diff HEAD~ > my.patch

Patches to info.yml files

If you are trying to patch a file that's modified by the Drupal.org packaging script (such as mymodule.info.yml), you may run into an issue with the patch working fine on code direct from the repo, but failing "in real life" on module code on an actual site. This can happen if there are contextual discrepancies due to the Drupal.org packaging script. If you find yourself in this situation, you can:

  • Create the patch with fewer lines of context than the default 3 lines of context:
    git diff -U1 origin/8.x-1.x > mypatchfile.patch
  • Create two patches -- one for folks to test "in the wild" / "in real life", one to actually apply to the module.

Tags

Help improve this page

Page status: No known problems

You can: