Introduction
Reviewing code via email is one of the simplest, most efficient, and most scalable approaches to code review. It can also be one of the most intimidating to get started with.
However, the crux of the workflow is simple: reviewing patches via email works the same way emails already work. You know how to use email — to review a patch you receive by email, you just reply to it with your feedback. There are some other tools we will familiarize you with, and some conventions and cultural norms to learn, but getting started with the basics is as easy as hitting "reply all".
Ultimately, everyone's email workflow is a bit different. No two maintainers agree on the best approach, and many people use different email clients, tools, custom scripts, workflows, and conventions. We'll just get you situated with an easy way to start in this tutorial and you can learn more and build a workflow that suits your needs over time. And, to any established mail users reading along: we're all sure that your preferred workflow is much better than the one explained here — but we can't please everyone 🙂
Introducing aerc
Effective use of the git email workflow requires you to choose an email client for which the workflow is comfortably accommodated for. This tutorial recommends aerc, an email client specifically designed to accommodate code reviews in your terminal emulator. It allows you to review patches comfortably, handles plain text emails well, and supports writing reviews in your editor of choice — vim, emacs, etc.
Just keep this in mind: you don't have to switch from your current email client of choice. You can just use both! aerc is lightweight and well-suited to being launched on-demand as a tool you only use during code reviews. Many people also use a separate email address just for development, or use mail filters to organize patches separately from other emails. Relax — you don't have to change your entire approach to email overnight to get started with code reviews via email.
aerc is probably available via your system package manager, and this is the recommended way to install it. The initial configuration is straightforward — just run `aerc` and follow the steps on screen. The built-in tutorial is sufficient to get you quickly acquainted with its usage, enough to move on to the rest of this tutorial. Here's a short screencast showing you what the process is like:
There are many other email clients you could choose, but this tutorial will assume you use aerc. Here are some other options you can research that work well with git:
Let's move on to the next step: getting some code to review.
Preparing the sandbox
We have prepared a sandbox environment for you to experiment with the email workflow in, including a git repository based on real-world software prepared for you to experiment with and a sample of some real-world patches and discussions.
Start by cloning the sandbox project on your machine:
git clone https://git.sr.ht/~sircmpwn/git-email-demo cd git-email-demo
Ctrl
+ T
in aerc to open an embedded terminal to run
these commands in.
Feel free to explore the code if you like — but don't worry if
you're not comfortable with C, you don't need to be for this
tutorial. You can compile it by running make
and run the
test suite with make check
.
Next, we're going to import some sample emails into aerc. Start by downloading the sample archive and using the following aerc commands to import it:
:mkdir sandbox
— create a sandbox folder (:rmdir -f
to remove it later):import-mbox ~/Downloads/sample.mbox
— edit the path as necessary
You should see the sample emails appear in your sandbox folder now.
You can press Shift
+ T
to toggle a threaded view if you prefer.
Reviewing a patch
Feel free to browse the discussions in this mailbox and familiarize yourself with the aerc interface. Try a little code review — read some of these patches and their revisions.
Let's try re-enacting the feedback Rene Kita offered on version 1 of
Kirill Chibisov's patch. Press r
q
to prepare a "quoted reply" to
this patch and type in some feedback:
Note that I'm editing the quoted text of Chibisov's email here to narrow in on the specific parts that I have feedback for. You can freely edit the email you're replying to to include feedback inline, between quoted sections, in whatever manner makes your code review easiest to understand. Unlike some common email workflows, the git approach encourages you to make as many edits to the text you're quoting as necessary to make your feedback clear. You can see Rene Kita doing something similar in their own review.
Applying and testing a patch
The tool we use to merge these patches into our git repositories is called git am — apply from mailbox. This tool accepts one or more email-formatted patches via the standard input and imports them onto the current branch of a git repository.
To import patches from aerc, you will first need to navigate aerc to
the directory containing the git repository. You can see aerc's
current working directory on the bottom right corner, in the status
bar. To update it, use the :cd <directory>
command,
e.g. :cd git-email-demo
. You can also navigate your
shell to the directory you want beforehand and start aerc there.
Ctrl
+ T
) will open in
aerc's current working directory.
Once we're situated in the appropriate git repository (maybe touching
it up with git pull
first), we can import the patches
using aerc's pipe command. Pressing the pipe key |
will prompt you
to enter a command to pipe the selected email into. Move the cursor
to a patch to import (try PATCH v3 from Chibisov), press the pipe
key, and enter "git am" as the desired command. Press q
once it
completes to dismiss the command output.
You can also import several patches at once. Press v
to mark one or
more messages, then use the same pipe command to pass all of them at
once to git am. Try this to import eschwartz's patches.
Once the patches you want are all imported, you can open a new
terminal tab to review them more closely — running tests and so
on. If you want to remove the patches, use git reset --hard
,
for instance git reset --hard origin/master
will remove
all patches which haven't yet been pushed to the upstream master
branch.
Here's what the whole process looks like:
Once you've applied all of the patches you're satisfied with, run
git push
to send them upstream, and don't forget to thank
the contributors for their patch! Note, however, that you don't have
push access to the demo repository — just keep this in mind for
when the time comes to review patches for your own projects.
Dealing with merge conflicts
Sometimes a patch will not apply cleanly if there have been changes
to the upstream repository between the time the patch was written and
the time of your code review. To address this case, we can use a
three-way merge with git am, similar to git merge
.
Simply run git am -3
instead of git am
to
request a three-way merge from git. This will allow git to resolve
trivial conflicts itself, and leave any other conflicts for you to
address on your own.
In case a patch did not apply cleanly with git am
or
git am -3
, git will leave the repository in an
intermediate state to allow you to examine it and resolve conflicts.
To revert your course without applying a troublesome patch, use
git am --abort
to restore the repository to its prior
state. Otherwise, as you resolve merge conflicts manually, use
git add
to mark each conflict as resolved, and finally
git am --continue
when all conflicts are resolved.
If you don't care to resolve the merge conflicts yourself, it's perfectly reasonable to ask the contributor to handle the rebase and to send you a new revision.
Advanced aerc usage
Here are some additional tips for getting the most out of aerc for code review.
aerc-patch(7)
aerc offers additional features for local management of patch sets which may be useful to those for whom the workflow is intuitive, particularly when managing many patches or many patch revisions. Consult aerc-patch(7) for more details.
Recommended keybindings for quick git use
You can add additional custom keybindings to
~/.config/aerc/binds.conf
. Here are a few extra
recommendations:
[messages] # Apply the selected patch(es) and flag the email ga = :flag<Enter>:pipe -mb git am -3<Enter> # Run git push gp = :term git push<Enter> # Browse the git log gl = :term git log<Enter>
Replying "thanks!"
Many aerc users have an email template which "thanks" contributors
for their patch once applied and summarizes the git push that
included it upstream. Add the following to
~/.config/aerc/templates/thanks
:
Thanks! {{exec "{ git remote get-url --push origin; git reflog -2 origin/master --pretty=format:%h | xargs printf '%s\n' | tac; } | xargs printf 'To %s\n %s..%s master -> master'" ""}}
And ~/.config/aerc/templates/quoted_thanks
:
Thanks! {{exec "{ git remote get-url --push origin; git reflog -2 origin/master --pretty=format:%h | xargs printf '%s\n' | tac; } | xargs printf 'To %s\n %s..%s master -> master'" ""}} On {{dateFormat (.OriginalDate | toLocal) "Mon Jan 2, 2006 at 3:04 PM MST"}}, {{(index .OriginalFrom 0).Name}} wrote: {{wrapText .OriginalText 72 | quote}}
Use :reply -Tthanks
to reply to a patch with this
template, or update binds.conf accordingly:
[messages] rt = :reply -a -Tthanks<Enter> Rt = :reply -qa -Tquoted_thanks<Enter>
Use rt
to send a simple "thanks" message, or
Rt
to include a quote from the original message for
further comment.
Further resources
Articles:
- git send-email: The contributor side of this workflow
- Email clients info for Linux: Resources for Linux kernel hackers
Videos:
Other:
- b4: a more advanced tool designed for Linux development