Skip to content

Commit 742789a

Browse files
LemmingAvalanchegitster
authored andcommitted
doc: add caveat about roundtripping format-patch
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: i3/i3#6564 (comment) † 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/ https://lore.kernel.org/git/V2_format-patch_caveats.34b@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> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 67ad421 commit 742789a

5 files changed

Lines changed: 60 additions & 3 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Patches produced by linkgit:git-format-patch[1] are inline. This means
2+
that the output from that command can lead to a different commit message
3+
when applied with linkgit:git-am[1]. It can also mean that the patch
4+
that is applied is not the same as the one that was generated, or that
5+
the patch application fails outright.
6+
ifdef::git-am[]
7+
See the <<discussion,DISCUSSION>> section above for the syntactic rules.
8+
endif::git-am[]
9+
10+
ifndef::git-am[]
11+
Any line that is of the form:
12+
13+
include::format-patch-end-of-commit-message.adoc[]
14+
15+
will terminate the commit message and cause the patch machinery to start
16+
searching for patches to apply.
17+
endif::git-am[]
18+
19+
Note that this is especially problematic for unindented diffs that occur
20+
in the commit message; the diff in the commit message might get applied
21+
along with the patch section, or the patch application machinery might
22+
trip up because the patch target doesn't apply. This could for example
23+
be caused by a diff in a GitHub Markdown code block.
24+
25+
This loss of fidelity might be simple to notice if you are applying
26+
patches directly from a mailbox. However, changes originating from Git
27+
could be applied in bulk, in which case this would be much harder to
28+
notice. This could for example be a Linux distribution which uses patch
29+
files to apply changes on top of the commits from the upstream
30+
repositories. This goes to show that this behavior does not only impact
31+
email workflows.
32+
33+
Given these limitations, one might be tempted to use a general-purpose
34+
utility like patch(1) instead. However, patch(1) will not only look for
35+
unindented diffs (like linkgit:git-am[1]) but will try to apply indented
36+
diffs as well.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
* three-dashes and end-of-line, or
2+
* a line that begins with "diff -", or
3+
* a line that begins with "Index: "

Documentation/git-am.adoc

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ applying.
233233
create an empty commit with the contents of the e-mail message
234234
as its log message.
235235

236+
[[discussion]]
236237
DISCUSSION
237238
----------
238239

@@ -254,13 +255,14 @@ line is automatically stripped.
254255
The patch is expected to be inline, directly following the
255256
message. Any line that is of the form:
256257

257-
* three-dashes and end-of-line, or
258-
* a line that begins with "diff -", or
259-
* a line that begins with "Index: "
258+
include::format-patch-end-of-commit-message.adoc[]
260259

261260
is taken as the beginning of a patch, and the commit log message
262261
is terminated before the first occurrence of such a line.
263262

263+
This means that the contents of the commit message can inadvertently
264+
interrupt the processing (see the <<caveats,CAVEATS>> section below).
265+
264266
When initially invoking `git am`, you give it the names of the mailboxes
265267
to process. Upon seeing the first patch that does not apply, it
266268
aborts in the middle. You can recover from this in one of two ways:
@@ -283,6 +285,13 @@ commits, like running 'git am' on the wrong branch or an error in the
283285
commits that is more easily fixed by changing the mailbox (e.g.
284286
errors in the "From:" lines).
285287

288+
[[caveats]]
289+
CAVEATS
290+
-------
291+
292+
:git-am: 1
293+
include::format-patch-caveats.adoc[]
294+
286295
HOOKS
287296
-----
288297
This command can run `applypatch-msg`, `pre-applypatch`,

Documentation/git-format-patch.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,10 @@ if they are part of the requested range. A simple "patch" does not
798798
include enough information for the receiving end to reproduce the same
799799
merge commit.
800800
801+
'''
802+
803+
include::format-patch-caveats.adoc[]
804+
801805
SEE ALSO
802806
--------
803807
linkgit:git-am[1], linkgit:git-send-email[1]

Documentation/git-send-email.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,11 @@ Links of a few such community maintained helpers are:
692692
- https://github.com/AdityaGarg8/git-credential-email[git-msgraph]
693693
(cross platform client that can send emails using the Microsoft Graph API)
694694

695+
CAVEATS
696+
-------
697+
698+
include::format-patch-caveats.adoc[]
699+
695700
SEE ALSO
696701
--------
697702
linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)

0 commit comments

Comments
 (0)