git-format-patch(1) and git-am(1) deal with formatting commits as
patches and applying them, respectively. Naturally they use a few
delimiters to mark where the commit message ends. This can lead to
surprising behavior when these delimiters are used in the commit
message itself.
git-format-patch(1) will accept any commit message and not warn or error
about these delimiters being used.[1]
Especially problematic is the presence of unindented diffs in the commit
message; the patch machinery will naturally (since the commit message
has ended) try to apply that diff and everything after it.[2]
It is unclear whether any commands in this chain will learn to warn
about this. One concern could be that users have learned to rely on
the three-dash line rule to conveniently add extra-commit message
information in the commit message, knowing that git-am(1) will
ignore it.[4]
All of this is covered already, technically. However, we should spell
out the implications.
† 1: There is also git-commit(1) to consider. However, making that
command warn or error out over such delimiters would be disruptive
to all Git users who never use email in their workflow.
† 2: Recently patch(1) caused this issue for a project, but it was noted
that git-am(1) has the same behavior[3]
† 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425
† 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/
https://lore.kernel.org/git/V3_format-patch_caveats.354@msgid.xyz/
Reported-by: Matthias Beyer <mail@beyermatthias.de>
Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>
Reported-by: Matheus Tavares <matheus.tavb@gmail.com>
Reported-by: Chris Packham <judge.packham@gmail.com>
Helped-by: Jakob Haufe <sur5r@sur5r.net>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Kristoffer Haugsbakk committedFeb 12, 2026 at 23:28 UTCa454cdca42fda0afaade73d7e90010289d1e7ba8
5 files changed+62-7
Documentation/format-patch-caveats.adoc
+33
new file mode 100644index 0000000000..807a65b885--- /dev/null+++ b/Documentation/format-patch-caveats.adoc@@ -0,0 +1,33 @@+The output from linkgit:git-format-patch[1] can lead to a different+commit message when applied with linkgit:git-am[1]. The patch that is+applied may also be different from the one that was generated, or patch+application may fail outright.+ifdef::git-am[]+See the <<discussion,DISCUSSION>> section above for the syntactic rules.+endif::git-am[]++ifndef::git-am[]+include::format-patch-end-of-commit-message.adoc[]+endif::git-am[]++Note that this is especially problematic for unindented diffs that occur+in the commit message; the diff in the commit message might get applied+along with the patch section, or the patch application machinery might+trip up because the patch target doesn't apply. This could for example+be caused by a diff in a Markdown code block.++The solution for this is to indent the diff or other text that could+cause problems.++This loss of fidelity might be simple to notice if you are applying+patches directly from a mailbox. However, changes originating from Git+could be applied in bulk, in which case this would be much harder to+notice. This could for example be a Linux distribution which uses patch+files to apply changes on top of the commits from the upstream+repositories. This goes to show that this behavior does not only impact+email workflows.++Given these limitations, one might be tempted to use a general-purpose+utility like patch(1) instead. However, patch(1) will not only look for+unindented diffs (like linkgit:git-am[1]) but will try to apply indented+diffs as well.
new file mode 100644index 0000000000..ec1ef79f5e--- /dev/null+++ b/Documentation/format-patch-end-of-commit-message.adoc@@ -0,0 +1,8 @@+Any line that is of the form:++* three-dashes and end-of-line, or+* a line that begins with "diff -", or+* a line that begins with "Index: "++is taken as the beginning of a patch, and the commit log message+is terminated before the first occurrence of such a line.
Documentation/git-am.adoc
+12-7
index 0c94776e29..972398d457 100644--- a/Documentation/git-am.adoc+++ b/Documentation/git-am.adoc@@ -233,6 +233,7 @@ applying. create an empty commit with the contents of the e-mail message as its log message.+[[discussion]] DISCUSSION ----------@@ -252,14 +253,11 @@ where the patch begins. Excess whitespace at the end of each line is automatically stripped. The patch is expected to be inline, directly following the-message. Any line that is of the form:+message.+include::format-patch-end-of-commit-message.adoc[]-* three-dashes and end-of-line, or-* a line that begins with "diff -", or-* a line that begins with "Index: "--is taken as the beginning of a patch, and the commit log message-is terminated before the first occurrence of such a line.+This means that the contents of the commit message can inadvertently+interrupt the processing (see the <<caveats,CAVEATS>> section below). When initially invoking `git am`, you give it the names of the mailboxes to process. Upon seeing the first patch that does not apply, it@@ -283,6 +281,13 @@ commits, like running 'git am' on the wrong branch or an error in the commits that is more easily fixed by changing the mailbox (e.g. errors in the "From:" lines).+[[caveats]]+CAVEATS+-------++:git-am: 1+include::format-patch-caveats.adoc[]+ HOOKS ----- This command can run `applypatch-msg`, `pre-applypatch`,
Documentation/git-format-patch.adoc
+4
index 9a7807ca71..bac9b818f3 100644--- a/Documentation/git-format-patch.adoc+++ b/Documentation/git-format-patch.adoc@@ -798,6 +798,10 @@ if they are part of the requested range. A simple "patch" does not include enough information for the receiving end to reproduce the same merge commit.+=== PATCH APPLICATION++include::format-patch-caveats.adoc[]+ SEE ALSO -------- linkgit:git-am[1], linkgit:git-send-email[1]
Documentation/git-send-email.adoc
+5
index ebe8853e9f..0b118df649 100644--- a/Documentation/git-send-email.adoc+++ b/Documentation/git-send-email.adoc@@ -692,6 +692,11 @@ Links of a few such community maintained helpers are: - https://github.com/AdityaGarg8/git-credential-email[git-msgraph] (cross platform client that can send emails using the Microsoft Graph API)+CAVEATS+-------++include::format-patch-caveats.adoc[]+ SEE ALSO -------- linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)