Rerolling patches

Last updated on
27 February 2023

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

What is rerolling?

Rerolling is the process of taking a patch that was made in one version of the software source code (for any project), and adapting it for a different version of the software. Reasons that a patch may need to be rerolled:

  • Commits from other issues and patches have been made in the same area of code covered by the patch, so it can no longer be applied successfully.
  • The patch was made for one branch or version of the software, and needs to be adapted to apply to a different version of the software (such as a patch for version 8.x being adapted for 7.x).

How to tell a patch needs to be rerolled

The automated patch testing system tests whether a patch applies or not. You may see a patch on an issue with a message like "Unable to apply patch [patchname]. Unable to apply patch…" beside it:

A patch with the 'Unable to apply' message from the automated patch testing system shown.

For some issues, people may tag the issue "Needs reroll", indicating that it is time to make a patch for a different version of the software, or that they manually tried to apply the patch and it didn't work.

Instructions for rerolling a patch

  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. Verify that you are on the correct branch of the repository (git status) or check out the correct branch (git checkout branchname).
  3. Create a local "feature branch" for the issue you're working on.
    git checkout -b [issue-number]-[short-description] # e.g. 123456-some-bug
    
  4. Find the latest patch on the issue by clicking the 'Most recent attachment' link on the top right of the page (or find the patch that you need to reroll, if for some reason it is not the latest patch). Download the patch to the root directory of the project.
    The top right section of an issue page with the 'Most recent attachment' link highlighted.
  5. Double-check whether it's necessary to reroll the patch (sometimes the testbot gets confused):
    git apply --check 1497310-statistics_config_settings-5.patch
    If you see no output, it was a false alarm: the patch doesn't need to be rerolled. If the issue had the "needs reroll" tag, remove the tag and post a comment that says something like: "I could apply the patch, so no reroll is needed." Reset the status to "Needs review". You're done!
  6. Go to the issue and note the date of the comment that you downloaded the patch from. (Double-click on the date to toggle between time-ago and the date and time.)A comment in an issue queue that's passing testbot, with the date circled

    Run the git log command with that date and time, in order to figure out a commit where the patch is applied cleanly. For example:

    git log  --before="March 30, 2012 at 1:54pm"
    
    commit 72cf5a75537a651c79271a1a3a6781ffc98430e7
    Author: catch <catch@35733.no-reply.drupal.org>
    Date:   Fri Mar 30 13:42:49 2012 +0900
    
        Revert "Issue #787652 by larowlan, andypost: Fixed Forum vocabulary alterations possibly obsolete -- possible to delete forum vocab."
    
        This reverts commit e179ee1d643101ae9ac9c1a94990bdb161ac8a62.
    
  7. Take the first few characters of the commit hash you see there (in this case, 72cf5a755) and create a new branch (and switch to it) from that commit.
    git checkout -b test-branch 72cf5a755
    

    git should return a line like the following:

    Switched to a new branch 'test-branch'
    

    During this process, you might encounter a permissions error like:

    error: unable to unlink old 'sites/default/default.settings.php' (Permission denied)
    

    To fix this error, make sure you have to write permission to the file and directory in which the file exists.

  8. Try applying the patch to test if it works:
     
    git apply --index 1497310-statistics_config_settings-5.patch
    
    (no output)
    

    If you get similar "patch does not apply" errors, delete your current branch and repeat from step 5 using an earlier date.

  9. Commit the patch's changes to your local branch.
    git commit -m "Applying patch from issue 1497310 comment 5804956"
    
    [test-branch 00329ef] Applying patch from issue 1497310 comment 5804956
     7 files changed, 99 insertions(+), 66 deletions(-)
     create mode 100644 core/modules/statistics/config/statistics.settings.xml
    
  10. Now, attempt to pull in all of the changes that have happened since the commit you branched from, which is known as a rebase:
    git rebase 8.9.x
    

    If the rebase has conflicts, this will take more work -- see the section below to deal with them.

  11. Create your patch by diffing your local branch (test-branch) against the upstream branch:
    git diff -M 8.9.x test-branch > test-branch.patch
    
  12. Test your patch by applying it to the upstream branch.
     
    git checkout 8.9.x
    
    Switched to branch '8.9.x'
    
    git apply --check test-branch.patch
    
    (no output)
    

    No output is good. That means the patch applied cleanly.

  13. Check the size of the patch. If it is zero bytes go through these steps again until it is larger than zero bytes. If it is a very different size from the original patch, then something probably went wrong during the reroll. There still needs to be more investigation on this patch.
  14. Check locally that the changes pass the pre-commit checks, following the steps in running core development checks.
  15. Save your changes:
    • Upload the patch to the issue (and optional plain diff -- see What about an interdiff?).
    • Change the issue Status to "needs review!"
    • Indicate in a comment whether it was an auto-merge, if there were conflicts, or if the file sizes were very different. If there were conflicts, describe what you did to resolve them. This will make it easier for the person reviewing the patch to know how carefully they need to review it.
    • Remove the "Needs reroll" tag.
    • Submit your comment and issue changes.

What about an interdiff?

You can't make a conventional interdiff on a reroll; see the reroll section on Creating an interdiff for the reasons and what to do instead.

Dealing with rebase conflicts

In step 10 above, you may find that when you try to rebase the repository, you come up with conflicts, meaning that the proposed changes in the patch conflict with other changes that were committed between when the patch was created and the current version. You might see output like this:

git rebase 8.0.x<br />
First, rewinding head to replay your work on top of it...<br />
Applying: patch<br />
Using index info to reconstruct a base tree...<br />
Falling back to patching base and 3-way merge...<br />
CONFLICT (modify/delete): core/modules/statistics/statistics.test deleted in HEAD and modified in patch. Version patch of core/modules/statistics/statistics.test left in tree.<br />
Auto-merging core/modules/statistics/statistics.module<br />
CONFLICT (content): Merge conflict in core/modules/statistics/statistics.module<br />
Auto-merging core/modules/statistics/statistics.install<br />
CONFLICT (content): Merge conflict in core/modules/statistics/statistics.install<br />
Auto-merging core/modules/statistics/statistics.admin.inc<br />
CONFLICT (content): Merge conflict in core/modules/statistics/statistics.admin.inc<br />
CONFLICT (modify/delete): core/modules/search/search.test deleted in HEAD and modified in patch. Version patch of core/modules/search/search.test left in tree.<br />
Failed to merge in the changes.<br />
Patch failed at 0001 patch<br /><br />
When you have resolved this problem run "git rebase --continue".<br />
If you would prefer to skip this patch, instead run "git rebase --skip".<br />
To check out the original branch and stop rebasing run "git rebase --abort".

To deal with this problem, you will need to go through each of the files listed as having conflicts and fix them. You can see a list of the files with conflicts by running the git status command and looking under 'Unmerged paths:'. For each file that has a conflict:

  1. Open the file in a text editor.
  2. Look for a line like <<<<<<< HEAD. For example:
    ...
      drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
    
    <<<<<<< HEAD
      if (variable_get('statistics_enable_access_log', 0)) {
    =======
        drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
      // Get the configuration for the settings.
      $config = config('statistics.settings');
      $statistics_count_content_views = $config->get('statistics_count_content_views');
      $statistics_enable_access_log = $config->get('statistics_enable_access_log');
    
      if (!empty($statistics_count_content_views)) {
        // We are counting content views.
        if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == NULL) {
          // A node has been viewed, so update the node's counters.
          db_merge('node_counter')
            ->key(array('nid' => arg(1)))
            ->fields(array(
              'daycount' => 1,
              'totalcount' => 1,
              'timestamp' => REQUEST_TIME,
            ))
            ->expression('daycount', 'daycount + 1')
            ->expression('totalcount', 'totalcount + 1')
            ->execute();
        }
      }
      if (!empty($statistics_enable_access_log)) {
    >>>>>>> your-branch-name
    ...
    

    Everything above  ======= is from the "clean" upstream version. Everything below the ======= is found in the patch you are rerolling. In general, you want to keep what's in the clean upstream version, and then modify it to follow the changed behavior from the patch. This ensures that any other changes that have been made to the upstream version not affecting your patch do not accidentally get undone.

  3. Edit the file until it looks correct, making sure to remove the special conflict marker lines. For example:
    ...
      drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
    
      if (config('statistics.settings')->get('statistics_enable_access_log')) {
         drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
    ...
    
  4. Stage your changes with
    git add .
    

    Be careful not to accidentally stage files that have been removed in HEAD. Use git rm for those if necessary.

  5. In order to continue the rebase process run: git rebase --continue

When you have completed all of these steps for all the files, return to step 11 above to make your patch.

Tip for handling conflicts -- USE WITH CAUTION: If the conflict situation isn't too complex and you know you need to keep the file changes from your commit (i.e. if the changes found in the patch you're rerolling are all intentional and no unrelated changes from the clean upstream will be lost), you may be able to use the super cool --theirs flag to speed things up. Read the documentation and the details of your code conflicts carefully before using! (In particular, a comment on that page: "Note: When doing a rebase, "ours" is the history branch and "theirs" is branch being replayed" -- and/or, the "tl;dr" on this other guide is really great!)

Tags

Help improve this page

Page status: No known problems

You can: