Rahul Raghunath
Rahul Raghunath

Reputation: 175

Send patches against first email through git send-email

I am currently working on a small assignment from an extra course in college. The task is to write a small program that does some work x, and a Makefile for it. We are to send the two files as a plain text email to our lecturer. We are then required to make a few changes to the program and send the changes as a patch to the first email. We are required to do this again.

Something like this:

program1 |--> patch for change2 |--> patch for change3

While i have no issues with the programming part, i'm having difficulty understanding how i could achieve this through git send-email. A detailed elucidation of the process for a beginner would be very much appreciated.

Upvotes: 3

Views: 3541

Answers (3)

Guildenstern
Guildenstern

Reputation: 3754

Here’s how you can do several rounds of review via email:

  • Optionally tag your current version (this will come in handy for the next round)
    • Optionally also tag the base commit (the commit on top of which you are basing your branch)
  • Prepare the first version: git format-patch --cover-letter --output-directory patches --thread=shallow
    • Edit the cover letter (patches/0000-cover-letter*): add a body (see the asterisks) and fix the subject (see the asterisks)
    • Regarding “links”: this command will create a Message-ID for the cover letter, which will be the first email in the email thread. Each of the patches will reply to the cover letter (“shallow” style).
  • Note down the Message-ID of your cover letter; it’s one of the email headers inside the text/patch file
  • Send it out using git send-email patches

Second round:

  • Optionally tag the current version
  • Do git format-patch again but with some additional options:
    • --in-reply-to=<Message-ID>: use the Message-ID from the first round that you made a note of
    • -v 2 for “second round”
    • Optionally use --range-diff <base> <previous tag> <current> in order to generate a “range diff” (the difference between the two series/branches) for the cover letter
      • This is where those optional tags come in handy
  • In the cover letter you can either discuss only what changed, or discuss what changed and in addition give the whole context from the first round (copy–paste works)
  • Do the rest

References

Based in part on SubmittingPatches.

Upvotes: 1

VonC
VonC

Reputation: 1323045

Note that just before the "Send this email" part, you can also use the --validate option in order to call the hook sendemail-validate (ie, an executable named 'sendemail-validate' in the hook path (by default .git/hooks)

That allows you to make some checks before sending those patches.

With Git 2.32 (Q2 2021), "git send-email"(man) learned to honor the core.hooksPath configuration, a Git 2.9 setting that I mentioned here before.

See commit c824393 (23 Mar 2021) by Robert Foss (robertfoss).
(Merged by Junio C Hamano -- gitster -- in commit 1ba947c, 30 Mar 2021)

git-send-email: Respect core.hooksPath setting

Signed-off-by: Robert Foss
Signed-off-by: Ævar Arnfjörð Bjarmason

get-send-email currently makes the assumption that the 'sendemail-validate' hook exists inside of the repository.

Since the introduction of 'core.hooksPath' configuration option in 867ad08 ("hooks: allow customizing where the hook directory is", 2016-05-04, Git v2.9.0-rc0 -- merge listed in batch #13), this is no longer true.

Instead of assuming a hardcoded repo relative path, query git for the actual path of the hooks directory.


Note that with Git 2.32 (Q2 2021), "git send-email --validate"(man) option message are changing.

See commit ea7811b, commit d21616c, commit e585210 (06 Apr 2021) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit 2279289, 13 Apr 2021)

git-send-email: improve --validate error output

Signed-off-by: Ævar Arnfjörð Bjarmason

Improve the output we emit on --validate error to:

  • Say "FILE:LINE" instead of "FILE: LINE", to match "grep -n", compiler error messages etc.
  • Don't say "patch contains a" after just mentioning the filename, just leave it at "FILE:LINE: is longer than[...].
    The "contains a" sounded like we were talking about the file in general, when we're actually checking it line-by-line.
  • Don't just say "rejected by sendemail-validate hook", but combine that with the system_or_msg() output to say what exit code the hook died with.

I had an aborted attempt to make the line length checker note all lines that were longer than the limit.
I didn't think that was worth the effort, but I've left in the testing change to check that we die as soon as we spot the first long line.

So instead of:

 patch contains a line longer than 998 characters

You have:

 is longer than 998 characters\n" .

With Git 2.35 (Q1 2022), the command line completion for "git send-email"(man) options have been tweaked and does mention format-patch.

See commit a2ce608, commit 2b7b758 (25 Oct 2021) by Thiago Perrotta (thiagowfx).
(Merged by Junio C Hamano -- gitster -- in commit 7c2abf1, 29 Nov 2021)

send-email docs: add format-patch options

Signed-off-by: Thiago Perrotta

git-send-email(1) does not mention that "git format-patch"(man) options are accepted.
Augment SYNOPSIS and DESCRIPTION to mention it.

git send-email now includes in its man page:

  • 'git send-email' [<options>] <file|directory>...
  • 'git send-email' [<options>] <format-patch options>

[...] be passed to git send-email, as well as options understood by git format-patch.


"git send-email -v 3"(man) used to be expanded to git send-email --validate 3 when the user meant to pass them down to format-patch: that has been corrected with Git 2.40 (Q1 2023).

See commit 8774aa5 (26 Nov 2022) by Kyle Meyer (kyleam).
(Merged by Junio C Hamano -- gitster -- in commit 531d13d, 27 Jan 2023)

send-email: relay '-v N' to format-patch

Signed-off-by: Kyle Meyer

send-email relays unrecognized arguments to its format-patch call.
Passing '-v N' leads to an error because -v is consumed as send-email's --validate.
For example,

git send-email -v 3 @{u}

fails with

fatal: ambiguous argument '3': unknown revision or path not in the
working tree.  [...]

To prevent this, add the short --reroll-count option to send-email's main option list and explicitly provide it to the format-patch call.

There other format-patch options that send-email doesn't relay properly, including at least -n, -N, and the diff option -D.
Punt on these because dealing with them is more complicated:

  • they would require configuring send-email to not ignore option case
  • send-email makes three GetOptions() calls with different sets of options, the last being the main set of options.
    Unlike -v, which is consumed by the last GetOptions call, the -n, -N, and -D options are consumed as abbreviations by the earlier calls.

With Git 2.41 (Q2 2023), the sendemail-validate validate hook learned to pass the total number of input files and where in the sequence each invocation is via environment variables.

See commit 3c8d3ad (14 Apr 2023) by Robin Jarry (rjarry).
(Merged by Junio C Hamano -- gitster -- in commit c4c9d55, 25 Apr 2023)

send-email: export patch counters in validate environment

Suggested-by: Phillip Wood
Signed-off-by: Robin Jarry

When sending patch series (with a cover-letter or not) sendemail-validate is called with every email/patch file independently from the others.
When one of the patches depends on a previous one, it may not be possible to use this hook in a meaningful way.
A hook that wants to check some property of the whole series needs to know which patch is the final one.

Expose the current and total number of patches to the hook via the GIT_SENDEMAIL_PATCH_COUNTER and GIT_SENDEMAIL_PATCH_TOTAL environment variables so that both incremental and global validation is possible.

Sharing any other state between successive invocations of the validate hook must be done via external means.
For example, by storing it in a git config(man) sendemail.validateWorktree entry.

githooks now includes in its man page:

The following environment variables are set when executing the hook.

GIT_SENDEMAIL_FILE_COUNTER

A 1-based counter incremented by one for every file holding an e-mail to be sent (excluding any FIFOs). This counter does not follow the patch series counter scheme. It will always start at 1 and will end at GIT_SENDEMAIL_FILE_TOTAL.

GIT_SENDEMAIL_FILE_TOTAL

The total number of files that will be sent (excluding any FIFOs).
This counter does not follow the patch series counter scheme. It will always be equal to the number of files being sent, whether there is a cover letter or not.

These variables may for instance be used to validate patch series.

The sample sendemail-validate hook that comes with Git checks that all sent patches (excluding the cover letter) can be applied on top of the upstream repository default branch without conflicts. Some placeholders are left for additional validation steps to be performed after all patches of a given series have been applied.


Still with Git 2.41 (Q2 2023), "git send-email"(man) learned to give the e-mail headers to the validate hook by passing an extra argument from the command line.

See commit a8022c5, commit 56addda (19 Apr 2023) by Michael Strawbridge (none).
(Merged by Junio C Hamano -- gitster -- in commit b6e9521, 10 May 2023)

send-email: expose header information to git-send-email's sendemail-validate hook

Cc: Luben Tuikov
Cc: Junio C Hamano
Cc: Ævar Arnfjörð Bjarmason
Acked-by: Luben Tuikov
Signed-off-by: Michael Strawbridge

To allow further flexibility in the Git hook, the SMTP header information of the email which git-send-email(man) intends to send, is now passed as the 2nd argument to the sendemail-validate hook.

As an example, this can be useful for acting upon keywords in the subject or specific email addresses.

githooks now includes in its man page:

This hook is invoked by git send-email.

It takes these command line arguments. They are,

  1. the name of the file which holds the contents of the email to be sent.
  2. The name of the file which holds the SMTP headers of the email.

The SMTP headers are passed in the exact same way as they are passed to the user's Mail Transport Agent (MTA). In effect, the email given to the user's MTA, is the contents of $2 followed by the contents of $1.

An example of a few common headers is shown below. Take notice of the capitalization and multi-line tab structure.

From: Example [email protected] To: [email protected] Cc: [email protected], A [email protected], One [email protected], [email protected] Subject: PATCH-STRING

Exiting with a non-zero status causes git send-email to abort before sending any e-mails.

Upvotes: 1

larsks
larsks

Reputation: 311238

Now you've asked some specific questions:

While i'm able to create the necessary patches for each of the sub assignments, i am unable to link all these three emails "somehow" in my lecturers mailbox

This is more of an email question that a git question. Emails are generally "linked" by replying to a previous message; in most clients, such a chain of replies will be displayed as a "thread" of conversation.

So after sending the first email, you would reply to it, possibly modifying the subject, and include the contents of the first patch (generated with git format-patch), and similarly for the second patch.

You can actually do this from the command line using git format-patch and git send-email. First generate your patches:

$ mkdir patches
$ git format-patch -o patches master

Then use git send-email to send these patches, taking advantage of the --in-reply-to command line option to link your messages to a previous message. This takes the message-id from a previous message as an argument, so you would need to look at your original message to get the value of the message-id header. Then you could run:

git send-email \
  --in-reply-to ...message-id-here... \
  --from [email protected] \
  --to [email protected] \
  patches

This will send two emails the subjects of which will look like:

[PATCH 1/2] first line of commit message here

And:

[PATCH 2/2] first line of next commit message here

For each email, git will prompt you whether or not you want to send it:

From: [email protected]
To: [email protected]
Subject: [PATCH 1/2] made a patch
Date: Thu,  3 Sep 2015 11:42:23 -0400
Message-Id: <[email protected]>
X-Mailer: git-send-email 2.4.0
In-Reply-To: <[email protected]>
References: <[email protected]>

    The Cc list above has been expanded by additional
    addresses found in the patch commit message. By default
    send-email prompts before sending whenever this occurs.
    This behavior is controlled by the sendemail.confirm
    configuration setting.

    For additional information, run 'git send-email --help'.
    To retain the current behavior, but squelch this message,
    run 'git config --global sendemail.confirm auto'.

Send this email? ([y]es|[n]o|[q]uit|[a]ll): 

The first will be a reply to the original message, and the second patch will be a reply to the first. In my mail client, this looks like:

   1   4  sF 03-09-2015 To lars@exampl  Test message for git                                         (➥)
   2   4 N F 03-09-2015 To lars@exampl  └─>[PATCH 1/2] made a patch                               (✉ me)
   3   4 N F 03-09-2015 To lars@exampl    └─>[PATCH 2/2] hey look no hands                        (✉ me)

(Note that for git to successfully send email you may need to provide it with some configuration. If it doesn't Just Work, git help send-email is the place to start.)

Upvotes: 1

Related Questions