How to submit a patch by email, 2023 edition
In 2009, I wrote a blog post How to submit a patch by email, which became popular at the time and also ended up in the PostgreSQL wiki. That article was written pre-Git and pre-cfbot, so maybe it’s time for a refresher, as we head into the next PostgreSQL development cycle.
The short answer is: Use git
format-patch
. That takes
care of almost all of the conventions and details. Looking at the
upcoming commit fests, it
appears that the vast majority of patch submissions already use that.
But I suspect that in some cases people produce the patches in some
other way and then rename them to look like what other people are
doing, without knowing about git format-patch
?
Here is the basic workflow:
$ git checkout -b my-feature-branch
# hack hack hack
$ git commit ...
$ git format-patch master
0001-Add-my-feature.patch
And if you later update your patch and want to send in a new version, you can do:
# hack hack hack
$ git commit --amend --reset
$ git format-patch -v2 master
v2-0001-Add-my-feature.patch
(You can also version your first patch as -v1
. Or you can try to be
optimistic and hope your patch won’t require a second version. ;-) )
You can also split up your submission into multiple commits:
$ git checkout -b my-feature-branch
# hack hack hack
$ git add ...
$ git commit ...
$ git add ...
$ git commit ...
$ git format-patch master
0001-Some-refactoring.patch
0002-Add-my-feature.patch
Exactly how to split up a submission into commits sensibly is perhaps the subject of another article, but in general it’s something that is encouraged and welcome.
Note the following features of what git format-patch
produces:
-
Patch files automatically get a descriptive name.
-
Patch files get the correct file extension.
-
Patch files are numbered so they sort easily.
-
When using versions, files belonging to a version sort together. (The alternative manual naming like “my-feature-v2.patch” is therefore wrong.)
Morever, since git format-patch
is based on commits, not working
tree state (like git diff
), it requires you to write a commit
message, which is highly encouraged, even if you are not a committer.
Obviously, the accompanying email will normally explain the patch as
well, but as threads get longer, it is no longer easy to find that
information. Having an up-to-date explanation in the patch itself is
vastly preferrable. Also, some committer will eventually have to
write the commit message. Getting that process started early makes
the final commit easier.
Also note that the output of git format-patch
is designed to be fed
into git am
to apply the patches.
I can easily apply a sequence of patches like this: git am
v5-*.patch
. Doing it any other way takes much longer and is much
more complicated.
git format-patch
has a lot of options, and trying to understand them
all can be overwhelming. For PostgreSQL work, you need almost none of
them. Here are a few options can you play with:
-
-1
,-2
, etc.: This specifies how many commits from the HEAD to make patches for. In the invocation that I have shown,git format-patch master
, it starts from where your development branch forked off themaster
branch. This is usually the best way to do it. But in some cases, if you have a complicated branch structure or made a mess, specifying it numerically is a good workaround. -
--minimal
,--patience
, and other diff algorithm options: This is optional, but in some cases choosing a different diff algorithm can make the patch look a bit nicer. -
-Oorderfile
: This can change the order of the files in the patch. See this blog post for an example. Personally, I wouldn’t go quite as far as that article suggests, because then it will make it harder for a reviewer to find the files in the patch if they don’t know the orderfile. The normal order that ends up being, doc, code, tests, is usually pretty sensible. Maybe movecontrib
to the end if your patch has to touch it but it’s not the primary focus of the patch. -
--base
: This option records what commit your patch series was based on. So someone who wants to apply the patch can use the same commit to apply it on, to avoid merge conflicts and guessing. To invoke it, just do something likegit format-patch master --base master
.
I do want to retract from my previous article the point about diffstats. I have come to find them useful. Leave them in, they don’t take up much space and don’t hurt anything.
Now finally, here is the most important thing when sending a patch,
something that git format-patch
cannot help you with. Make sure
your email program sends the attachments with an appropriate content
type. It should be text/x-patch
or text/x-diff
or
text/something
, but not application/octet-stream
. The latter
makes it harder to look at the patch in the email client or in the
email archives on
the web. If I’m casually browing patches, if an attachment is sent as
application/octet-stream
, I’m much less likely to look at it. There
are plenty of other patches to look at that don’t have that problem.
Summary:
- patches generated with
git format-patch
and applicable withgit am
- sent using suitable email content type