Advanced patch contributor guide

Thu, 01/26/2012 - 17:59

Almost all improvements to other peoples' projects come in the form of a self-contained set of changes, e.g., a bug fix against a particular module or include file, improvements to existing code, and so on. The exact changes are captured in a patch file — a simple text format that shows lines added and removed.

This page describes an advanced workflow that can help maintainers give you credit in the repository log by creating and uploading a patch containing instructions for one single commit to a project hosted on Drupal.org. For the general high-level overview of patching with git, see Making a patch with Git.

Prerequisite: Every workflow requires the initial set up detailed in Using Git on Drupal.org.

Obtain or update a copy of the project

  1. Clone the project to obtain a copy of it that you can work with locally. You only need to do this once per project.
    git clone --branch [version] http://git.drupal.org/project/[project_name].git
  2. If you didn't just clone for the first time, pull the latest changes down to ensure you're working on the latest code.
    git checkout [version]
    git pull

Creating patches via topic branch

  1. Create and checkout a local "topic branch" for the issue you're working on. (If the issue appears at http://drupal.org/node/123456 then the issue number is 123456.)
    git branch [issue-number]-[short-description] # e.g. 123456-example-bug
    git checkout [issue-number]-[short-description]

    Or in a single line:

    git checkout -b [issue-number]-[short-description] # e.g. 123456-example-bug
  2. Make whatever changes are necessary to see your issue fixed.
    # Edit file in your favorite editor:
    <your_editor_here> [filename]

    # After making your edits and saving the file, confirm your changes are present:
    git status

    # Make more edits in other files and save theme:
    <your_editor_here> [other-filename]

    # Confirm changes again:
    git status

  3. When you are satisfied, make one single commit with all your changes using the -a option.
    # Commit the changes to your topic branch
    git commit -a -m "Issue #123456: Fixed all instances of foo bug."

    See the Drupal.org documentation on commit messages for more details on commit message standards.

  4. When your code is ready to show people, grab the latest code once more.
    git fetch origin
  5. Make your code apply to the latest version of the code
    git rebase origin/[version] #e.g. [version] could be 7.x-2.x
  6. Now, create your patch file. Two methods of creating patches are as follows:
    1. The most generic (and fool-proof) way is to create a diff relative to the branch you just used for the rebase:
      git diff origin/[version] > [project_name]-[short-description]-[issue-number]-[comment-number].patch
    2. In the case where you have followed the instructions above and have just one SINGLE commit on your local topic branch you can use the git format-patch command to make a patch that will include your author information.
      git format-patch origin/[version] --stdout >  [project_name]-[short-description]-[issue-number]-[comment-number].patch
  7. Upload your patch to the Drupal.org issue attached to a new comment; remember to change the issue status to "needs review", to flag the issue for reviewers.

Patch naming conventions explained

The (unofficial) patch naming convention that has emerged from the community is:

[project_name]-[short-description]-[issue-number]-[comment-number].patch
[project_name]
refer's to the project's name as it appears in the URL of the project page on Drupal.org, i.e. http://drupal.org/project/[project_name], or from the git remote repository location, i.e. http://git.drupal.org/project/[project_name].git
[short-description]
is an 1-2 word summary about what the patch does with dashes between the words.
[issue-number]
appears in the URL of the issue on Drupal.org; For example, if the issue you're working on is at http://drupal.org/node/9876543, the issue number is 9876543.
[comment-number]
is the comment on the aforementioned issue that caused another patch file to be needed or the one that inspired the patch. If there is no comment causing the patch to be submitted then none is required for the filename or you can use a comment-number of 0 (zero) to indicate the original issue. If you're fixing, changing or improving upon a previously provided patch in a way that has not yet been documented in a previous comment, you may wish to guess at the comment number you're about to post by adding 1 to the last comment number on the issue; please note that this last option is an imperfect method that may not work as intended on active issues with many people commenting. In this case, the best advise is to redact your comment offline, and refresh the page just before you paste in your comment text and attach the patch.

Hypothetical example

A patch for a spelling error on the contributed module "my_module" and a suggested fix in comment #12 of issue #9876543 might look like: my_module-spelling-9876543-12.patch.

Footnotes

  • Do not use a hash sign (a.k.a. pound sign) "#" in your patch file's name as it does not work.
  • In general, automated testing of your patches on Drupal.org by the friendly testbot is a Good Thing. However, adding -DX at the end of the patch name will cause the testbot to skip testing of the patch. For example, my_module-spelling-9876543-13-D7.patch will be ignored.
  • The best practice recommendation is to use Git, however patches may be created with many tools. The minimum requirement for uploading patches to Drupal.org is that you must be able to apply the patch with patch -p1 or git apply.
  • Before creating a patch that spans many commits, users should use git rebase -i to squash their several commits into one if it's only one logical commit.
  • Following the nomenclature documented here, a Drupal core patch might look like: drupal-proper-title-987654321-23.patch. Please note that while some people opt to leave off the [project_name] from core patches, adding "drupal-" to the front helps distinguish core patches from others, and is therefore still recommended for consistency, clarity, and simplifying the instructions.
  • When you remove or move files in the repo using git rm or git mv, git diff creates a verbose output. Use git's format-patch command with the -C and -M options will move the file, instead of removing and adding the lines. The patch size becomes much smaller as a result of this.

    git format-patch -C -M [version] --stdout > [patch-name].patch

  • If you use git format-patch to create patches and you post them to Drupal.org, then the email and name you have configured in user.email and user.name will be widely indexed on the Internet, as Google picks up all our patches. If you don't want this, you may want to consider using the alternate git diff <main_branch> >/tmp/my_module.my_issue.patch method for creating patches.
  • When you add new files to the repository with git add, avoid use of the -N option, which causes any resulting patches to try to apply against a non-existent file.
  • Since patch files themselves should never be added to a project, you may wish to tell Git to ignore them globally by adding the line *.patch to a ~/.gitignore file, followed by the command: git config --global core.excludesfile ~/.gitignore. You can also use this for other types of files that Git should always ignored, like text editor backup files. For more information, see: gitignore Manual Page.
Tags: