Using git with email: a Quick Tutorial; by ~lymkwi (Lux Amelia) ; 1015 words ; about 6 minutes ;
updated 2023-12-08 (Fri);
I am mostly writing this as a self memo for how to use
git-send-email, and by
git-am, to share patches, patchsets, and
Me and my friends like to do these overly elaborate things to share code, what we jokingly call "fossbro roleplaying", so hopefully it can help them, and you as well!
"Wait what's all that about?"
These commands let you create patches that represent a commit (with all of its metadata, save for cryptographic signature), share them automatically over email, and, once someone downloads the contents of your email, apply those commits to a tree.
TL;DR: These are the settings you want to tweak. Mine would be:
git config --global sendemail.smtpencryption tls
git config --global sendemail.smtpserver smtp.vulpinecitrus.info
git config --global sendemail.smtpuser <user>
git config --global sendemail.smtpserverport 587
git config --global sendemail.from <my email>
These settings replace CLI parameters you can otherwise provide when sending
Exporting with format-patch
git-format-patch commands turns a commit or set of commits into files that
can be straightforwardly sent as email.
The only real positional argument provides the range or set of commits to format. That can be quite hard to wrap your head around but here's a quick rundown:
|All commits from
|All commits in the range from A (excluded) to B (included)
n commits from
Note that because
git is the way it is, and because, when you think about it,
it makes sense: when your range includes a divergence, you might pull all of the
divergent commit from it. It's just how
git works. In the end, you will get
all the commits you need, but they will be linearized, so the application order
might be a bit wonky or cause merge errors.
Everything else is just optional arguments. Here are those I think would be the most useful:
--rfc: your patch or patchset is a request for comments
-v <n>: mark this as version
<n>of your patchset
--cover-letter: generate a file that represents the cover letter, or the big description you send to explain the whole point of your patchset; by default it contains diff stats, and such
--thread=<style>: the thread style controls how your commits follow each other. A
shallowstyle means all subsequent email are a reply to the first one (typically the cover letter). That is the standard on LKLMs.
--in-reply-to=<message-id>: oddly enough, I have already had to send a patch as a reply to a human-made series of email. This may be useful for that purpose.
Sending with send-email
This is the big complex part. Technically,
git-send-email is a big Perl script
that wraps around calls to your mail sender. As such, you may find some missing
dependencies such as
perl-authen-sasl on Arch Linux.
send-email command takes your files and sends them as email. Easy. Except
it does a lot of things for you and is very fuzzy in terms of available options.
For example, it takes all emails from the
Signed-off-by: and such lines in
your commits, and adds them as
Cc: lines in the email sent unless you tell it
Here are the options I generally use:
--to=<email>: a new
--cc=: a new
--bcc=: a new
--compose: if you did not generate and edit a cover letter, write it now
--no-signed-off-by-cc: this removes the automated gathering of emails in the
--suppress-cc=<choice>: suppress automatically found
Cc:, you can see the man page for all choices
--dry-run: do everything but send the actual email; the information sent to the SMTP server is shown in the standard output for debugging purposes
There is actually an interesting overlap between
format-patch. You can actually configure most of everything you want for the
content of your email messages via either command, depending on your choice. For
example, had I not chosen threading style in
format-patch, I could have
specified it in
Applying with am
If you find yourself the (un?)fortunate recipient of a patchset that you fancy
adding to your project, you can simply download your email to files (or,
honestly, just copy the visible content from your email browser), and run
git am on them. Ideally, you want to apply them in order, and over the
correct commit. The details for how to coordinate with your collaborators for
that to happen is left at your own discretion.
Interestingly, you can use
am to sign the objects created. The
signature from the original committer in their own repository cannot be
maintained, because you create the actual binary
git objects tied to that
commit in the actual repository yourself, so you must sign and certify that
the content you create that commit with is valid. You are the first person
liable if something wrong is introduced (and others are on the line if there are
As as interesting side note, many places will let you download
that have the correct format to be an email and a
git patch. For example:
- GitHub lets you do so for individual commits by adding
.patchat the end of the URL, and similarly with pull requests (except the patch contains all individual patches for the PR's commits)
- GitLab does the exact same thing for both commits and merge requests
- Gitea/Forgejo also lets you do the same on both commits and PRs
As a result, you will often find yourself using
git am on things that are not
As an addendum, I can point you to another tutorial by Matheus Tavares.