Submitting Patches

From postmarketOS

Some projects use "email workflow" to accept contributions, instead of the "fork" based workflow you may be familiar with. Despite looking archaic, this is, in fact, workflow native to git as a distributed VCS. Essentially, with this workflow, you send the patches directly to the maintainers of the project and get review comments in response as a e-mail thread.

General workflow

b4

b4 is a tool created to make it easier for project developers and maintainers to use a distributed development workflow that relies on patches and distribution lists for code contributions and review.

You can use b4 to submit patches configuring your own SMTP server, or via a web-endpoint like the LKML has

A very good walkthrough of the whole process of creating and sending a patch has been detailed here: https://people.kernel.org/monsieuricon/sending-a-kernel-patch-with-b4-part-1

git send-mail

The workflow boils down to running git send-email with correct arguments to send patches via email.

Note that you may have to install git send-email as a dedicated package since many distributions split this feature into a sub-package.

You may find a semi-interactive tutorial on sending patches at https://git-send-email.io

Configuring git send-email

This is pretty well documented elsewhere, notably in the freedesktop pulseaudio docs and here: https://burzalodowa.wordpress.com/2013/10/05/how-to-send-patches-with-git-send-email/

To send patches from GMail, create an app password on https://myaccount.google.com/apppasswords .

Example config for GMail:

$ cat ~/.gitconfig
[sendemail]
       smtpEncryption = tls
       smtpServer = smtp.gmail.com
       smtpUser = username@gmail.com
       smtpServerPort = 587                                                   
       confirm = always

You may store your SMTP password with

$ git config --global sendemail.smtpPass 'your password'

but this is not mandatory as git would prompt you for the password every time if you decided to not save it.

Sending patches

In the most simple case you will just call

$ git send-email --to="Some Maintainer <someone@project.org>" <commit-hash-range>

which would make git create patches and send them via your email account. If you send a series of multiple patches or want to add some annotations before sending, add --annotate --cover-letter to open the editor and add a cover letter to the set. (You can think of the cover as of a PR description)

Do not send a cover letter with single patches. If you want to include a changelog between patch version for single patches, use -- and put it below that:

<Patch subject>

<Patch description>

--

<Changelog and other administrative information about patch>

Cover letters should have a subject marking the subsystem and driver. So let's say you modify a driver called fastrpc in misc subsystem and adjusted the dt-bindings docs for your change, it looks like this:

misc: fastrpc: <SUBJECT OF COVER LETTER>

This workflow is assumed for patches, but also cover letters!

Finding the commit range

Git has a lot of ways to define, which commits you want to include.

One of the easiest way to set a range is to use a count flag, i.e. if you want to use 3 last pathces it would be -3.

If all the patches you want to send reside on top of some branch or a tag, you can use the name of that tag to include all commits made after it (but not including the tagged commit itself)

You can specify commits starting from a hash, like this:

# note down the hash of the first commit in your series, e.g:
$ git log --oneline
9f0cfbc330a2 arm64: dts: qcom: sdm845-oneplus-common: add nodes for q6voice apr service
aa209f22271d arm64: dts: xiaomi-beryllium-common: Add nodes for q6voice apr service
0fe8a293245b arm64: dts: qcom: sdm845: Add q6voice APR service device nodes # <-- this is the first commit

# The caret '^' tells git to include the referenced commit, without it only the top 2 commits would be used
#                              $ git format-patch 0fe8a293245b^ 
0001-arm64-dts-qcom-sdm845-Add-q6voice-APR-service-device.patch
0002-arm64-dts-xiaomi-beryllium-common-Add-nodes-for-q6vo.patch
0003-arm64-dts-qcom-sdm845-oneplus-common-add-nodes-for-q.patch

You can also use relative commit reference instead of full commit SHA, like git format-patch HEAD~3 to generate patches for 3 last commits. This way you don't need to know the exact hashes of commits.

Addressing feedback

After you've sent a patch, you may get some feedback in response. The maintainer may ask you to make some changes or ask something about your code. If you want to answer to the comments, you can just write a response email in your preferred email client. Note that usually replies use inline style. Also some projects or maintainers prefer to only receive plaintext emails so make sure you don't send an HTML reply to someone who would not like that.

After you have made the asked changes locally and amended the commits, you can repeat the process, adding a version note to the patchset with -v2 flag where 2 means your second time sending this change. (Don't mistake this with a patch count flag discussed earlier!)

Project specific tips

Some projects have own specific quirks and traditions on submitting the patches. Thus this section gives more specific advice.

Linux

The Linux kernel traditionally uses the "git send-email" workflow for patch submission, once you have some commits you want included, you email them as git "patches" to the mailing list and any relevant maintainers. This can be a bit of a daunting task, there are many guides out there explaining how to do this, but they usually miss bits out or do a poor job of explaining how git send-email actually works.

The following is the description of the process used by multiple kernel hackers. It may not be perfect and you may find the need to make some modifications to suit your workflow the best. Yet this should be a good starting point.

Preparing your commits

While in many cases you may be able to send your commits immediately, you may want to make sure maintainers don't get merge conflicts trying to apply them. This can easily happen if you, for example, have changed some Makefile and your maintainer have recently applied another change touching it. To make sure that your changes apply to the maintainer's working tree, you can rebase them either on top of the maintainer's own Linux branch or on top of the latest linux-next which is a Linux tree that incorporates pending changes from most maintainers.

# (First time) Add linux-next into your local Linux tree
$ git remote add linux-next git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

# (Other times) Fetch the latest version of linux-next (it's updated daily)
$ git fetch linux-next

# Checkout latest version of -next (detached, we will not do any real work here) 
$ git checkout linux-next/master

# Cherry-pick your patches
$ git cherry-pick <commit-range>

After you do this (and, possibly, resolve some merge conflicts), your patches should be likely to apply for most maintainers. Note that you should update the base tree every time you re-submit your series in case some new conflicting change was applied in-between.

Checking formal patch rules

Linux has a special script that checks for the most common mistakes in patches. Run it to make sure you didn't miss anything obvious.

# Create patch files for all of your patches
$ git format-patch <commit-range>

# Check created patches
$ ./scripts/checkpatch.pl *.patch

You should get a report of found mistakes for each of the patches. Make sure to review it.

If you have errors, fix them, create a fixup commit for whichever patch(es) you had to fix (e.g. git commit --fixup aa209f22271d) and then squash the series again with git rebase -i 0fe8a293245b^, and start again. (You may want to make edits on your working branch and not on the detached head if you use it.)

Finding your maintainers

Linux kernel is a huge project. Because of this, there is no single person responsible for all patches. Instead there are dedicated maintainers for each subsystem of the kernel. They accept and review changes for their subsystem and then send collected patches "up the chain" either to some other, more general maintainer, or to Linus Torvalds to include into the next release.

This means that for each patchset you should know who to send your patches to. Kernel has a special index file (MAINTAINERS) and a script that parses it.

You can use get_maintainer.pl to find a list of emails to send your patch to:

# (Assuming the patches are kept from the previous step)

# Get a list of maintainers
$ ./scripts/get_maintainer.pl *.patch

# Remove now unneeded patches
$ rm *.patch

The script would give you a list of maintainers, reviewers and lists, to whom you will send your patches. Please review it as the script sometimes tries to "be smart" and includes previous contributors that may not have anything to do with your changes. If you see a person that has no role and only i.e. "lines changed" note, you may want to omit them.

Sending patches

Now, as we know recipients of our patches, we can start constructing our send command.

Add all recipients to the command line with either --to or --cc flags (of which you can repeat as many as you wish). If you want to order the recipients in a specific way, you may --to the primary subsystem maintainer(s) then --cc everyone else, putting the lists in the end. The order is mostly a matter of the personal preference and is not necessary to follow. As long as you include all the people, your patches will arrive.

If you include patches made by other people, include them into the recipients explicitly. Otherwise git may not send the full series to them. (you may want to ignore this rule for very big sets but at this point you should know what you are doing)

There is a handy bash function for this which formats the output so it can be directly appended to git send-email, you might want to add it to your .bashrc or wherever else...

gencclist () {
	echo "$(./scripts/get_maintainer.pl --nogit --nogit-fallback --norolestats --r "$@" | xargs -I {} echo --to=\"{}\" | tr '\n' ' ')"
}

Now we can simply run:

$ gencclist *.patch
--to="Some Maintainer <someone@kernel.org>" --to="linux-arm-msm@vger.kernel.org" --to="devicetree@vger.kernel.org" --to="linux-kernel@vger.kernel.org"

Finally, we're ready to send our patches, it's worth noting that the .patch files we generated are not used for this, instead git send-email produces the patches directly, it will format them properly for the kernel, including the patch version if necessary.

$ git send-email 0fe8a293245b^ --to="Some Maintainer <someone@kernel.org>" --to="linux-arm-msm@vger.kernel.org" --to="devicetree@vger.kernel.org" --to="linux-kernel@vger.kernel.org"
/tmp/EvaxiVuPLX/0001-arm64-dts-qcom-sdm845-Add-q6voice-APR-service-device.patch
/tmp/EvaxiVuPLX/0002-arm64-dts-xiaomi-beryllium-common-Add-nodes-for-q6vo.patch
/tmp/EvaxiVuPLX/0003-arm64-dts-qcom-sdm845-oneplus-common-add-nodes-for-q.patch

Or git send-email <...params...> *.patch

You can also use git send-email --to-cmd=./scripts/get_maintainer.pl .. to automatically use its results in --to arguments.

If you're sending a series and would like to include a cover letter, add the --annotate --cover-letter arguments to git send-email. This will automatically generate a shortlog and a diffstat for the series. I'd recommend writing your cover letter separately and pasting it in to avoid potentially losing data.

If your patches are a result of pmOS related work, dont forget to add --cc="~postmarketos/upstreaming@lists.sr.ht". You may also want to add --cc="phone-devel@vger.kernel.org" for phone related patches.

If you are including patches made by others, add --signoff flag to add your signoff on those.

Addressing the review comments

The general suggestions apply. Note that you MUST use plaintext email to respond to the Kernel mailing lists. Use reply-all when answering.

If you're asked to make changes, add a changelog into your cover letter or commit note:

- Changed in v2:
 - Did foo
 - Did bar
- Changed in v3:
 - Did baz

Keep all previous changelog entries when resubmitting.

You can also add the changelog to dedicated commits after a --- separator on the new line after the last signoff.

To send a new version of your patches (e.g. a version 2), add -v2. This works for all versions (e.g. -v5).

You may get a response like this:

> ...
Reviewed-by: Some Person <someperson@somewhere.com>

This is a tag given to you by that person. If you are in the need to send a new version of your patchset, you should include the given tag as-is with no changes made, into the commit that this response was given to (If the tag is given in response to the cover, you can add it to all the commits in the series). Note that you should NOT re-send a series if you only change the tags. Maintainers have tools to collect those automatically.

Dealing with different tags is explained in the Linux kernel documentation: Documentation/process/submitting-patches.rst.

Patches are not getting picked up

Sometimes patches may be missed, or some misunderstanding might happen. Generally in the Linux kernel it's the job of the contributor to track their patches and send reminders if needed. General advice is to resend a patch after two weeks of silence. (you should instruct git to prefix your patch as [PATCH Vx RESEND] (i.e. using --subject-prefix flag) if you are sending it again as is with no changes.) Make sure to check if your patch was already picked up before sending any reminders. Certain maintainers e.g. Mark Brown require always resending, do not ping them on the mailing list.

Rule of thumb: resend or ping after > 2 weeks of no response.

Subsystem specific

Each subsystem maintainer of the Linux kernel has its own workflow, based on experience we collected the following tips & tricks:

Devicetree Source (DTS) patches

Make sure you check their compliance and does not contain typos with make dtbs_check

If you also changes the Devicetree Bindings, you can run both checks together: make dt_binding_check dtbs_check

Qualcomm Devicetree Source (DTS) patches

Status of these patches is reflected in MSM Patchwork. A new version may be expected through Patchwork.

Rule of thumb: check the MSM patchwork page for the status.

Devicetree Binding patches

If you implement a feature in a driver which requires changes to the Devicetree bindings, it is conventional to first patch the Devicetree bindings in Documentation and then implement the feature in the driver. Patches are expected to follow this order as well.

You can check your patches compliance with make dt_binding_check.

Other maintainers

Ask the maintainer and describe here the general rule of thumb.

See also