@@ -42,13 +42,13 @@ surprising warning that had just circulated on Mastodon:
4242
4343The incident had originated in the i3 window manager project, where a
4444commit message contained an unindented diff for illustration purposes.
45- When Debian packagers later applied the patch using ` patch(1) ` , the diff
45+ When Debian packagers later applied the patch using patch(1), the diff
4646in the commit message was applied as actual code, sneaking a spurious
4747` sleep(1) ` call into the Debian unstable package. Matthias asked the
4848list whether this was a known issue and whether it could be an attack
4949vector.
5050
51- To understand why this happens, it helps to know how ` git-am ` parses
51+ To understand why this happens, it helps to know how git-am(1) parses
5252its input. When processing a patch email, it must split the stream into
5353two parts: the commit message and the actual patch to apply. It does
5454this by treating the first occurrence of any of the following lines as
@@ -59,23 +59,23 @@ the boundary between the two:
5959- a line beginning with ` Index: ` .
6060
6161Everything before that boundary becomes the commit message; everything
62- after is fed to the patch application machinery. Crucially, ` git-am `
62+ after is fed to the patch application machinery. Crucially, git-am(1)
6363scans from the top of the email, so the very first such line it
6464encounters terminates the commit message regardless of whether that
6565line was meant to be part of the message text.
6666
6767This design dates back to the tool's origins. As Jeff King (also known
68- as "Peff") quickly explained in reply to Matthias, ` git-am ` was
68+ as "Peff") quickly explained in reply to Matthias, git-am(1) was
6969originally designed to handle patches sent by all kinds of people, not
7070just Git users. A contributor might have generated a diff with plain
7171GNU ` diff ` and typed the rest of the email by hand, without any ` --- `
7272separator. The tool was therefore intentionally permissive: it would
7373find a ` diff - ` line anywhere in the email and treat it as the start
74- of the patch. Peff demonstrated this with a live example. He fed `git
75- am` a hand-typed email containing a GNU diff, and it produced the
74+ of the patch. Peff demonstrated this with a live example. He fed
75+ git-am(1) a hand-typed email containing a GNU diff, and it produced the
7676expected commit.
7777
78- This historical context also explained why ` git-am ` is notoriously
78+ This historical context also explained why git-am(1) is notoriously
7979hard to fix: "I don't think there is a way to unambiguously parse the
8080single-stream output that format-patch produces," Peff wrote, noting
8181that he could find at least three earlier discussions of the same
@@ -96,51 +96,51 @@ behavior was there. He called it "sheer luck" that it was only a
9696` sleep(1) ` and not something more malicious crafted as a diff in the
9797commit message.
9898
99- Florian Weimer wondered whether the ` git-format-patch ` output was
99+ Florian Weimer wondered whether the git-format-patch(1) output was
100100really ambiguous, given that the patch section is normally preceded by
101101a diffstat block. Peff replied that the diffstat is optional and is not
102102even parsed by the receiving side at all.
103103
104- Jakob Haufe added an important nuance: even if ` git-am ` were fixed to
104+ Jakob Haufe added an important nuance: even if git-am(1) was fixed to
105105require indented diffs, it would only partially mitigate the problem,
106- because ` patch(1) ` (which many distributions use to apply upstream
106+ because patch(1) (which many distributions use to apply upstream
107107fixes to packages) is even more permissive. It will strip a consistent
108108level of indentation from diffs before applying them. He quoted the
109- ` patch(1) ` manual page: "If the entire diff is indented by a
109+ patch(1) manual page: "If the entire diff is indented by a
110110consistent amount, [ ...] this is taken into account." The i3 incident
111- had in fact been triggered by ` patch(1) ` , not ` git-am ` .
111+ had in fact been triggered by patch(1), not git-am(1) .
112112
113113Kristoffer Haugsbakk synthesized this into a clear summary of the
114114situation and immediately proposed documenting it.
115115
116116Matthias also highlighted the broader applicability beyond email
117117workflows: Linux distributions like NixOS routinely fetch patches
118118directly from upstream Git repositories and apply them to packages
119- using ` patch(1) ` . He noted that even after 15 years of using Git and
119+ using patch(1). He noted that even after 15 years of using Git and
120120being comfortable with email patch workflows, he himself had not known
121121about this behavior.
122122
123123Several directions were then explored to look for solutions.
124124
125- Peff observed the irony that ` git-format-patch ` does have a ` --attach `
125+ Peff observed the irony that git-format-patch(1) does have a ` --attach `
126126option which puts the message and the patch in separate MIME parts —
127- making them unambiguous in principle. However, ` git-mailinfo ` (which
128- powers ` git-am ` under the hood) decodes both parts into a single
127+ making them unambiguous in principle. However, git-mailinfo(1) (which
128+ powers git-am(1) under the hood) decodes both parts into a single
129129stream and still treats a ` diff ` line in the message part as the start
130130of a patch. Fixing this would require careful surgery to avoid
131131breaking the existing forgiving handling of patches received as a
132132single attachment.
133133
134134Patrick Steinhardt suggested that even if parsing cannot be made
135- unambiguous, ` git-am ` could at least detect the ambiguity and bail by
135+ unambiguous, git-am(1) could at least detect the ambiguity and bail by
136136default with an ` --accept-ambiguous-patch ` override. Jacob Keller
137137proposed going further: a new "unambiguous mode" where
138- ` git-format-patch ` would produce output that new versions of ` git-am `
138+ git-format-patch(1) would produce output that new versions of git-am(1)
139139could distinguish unambiguously, while old versions would still handle
140140the common case the same way as before.
141141
142142Jacob had also sketched a concrete scheme: add a new unambiguous
143- marker after the ` --- ` separator, so that old versions of ` git-am `
143+ marker after the ` --- ` separator, so that old versions of git-am(1)
144144would still cut at the ` --- ` and ignore everything up to the diff, while
145145new versions would wait for the new marker and correctly ignore any
146146diff appearing before it. Since the new marker would come after ` --- ` ,
@@ -152,7 +152,7 @@ commit message, and both sides would need to complain if they saw
152152multiple markers. He explored further options: reversible quoting of
153153` --- ` and ` diff ` lines in the commit message (analogous to the ` >From `
154154quoting used in mbox files), applied only when the message would
155- otherwise be ambiguous. This way, if an older ` git-am ` received the
155+ otherwise be ambiguous. This way, if an older git-am(1) received the
156156mail, the worst case would be visible quoting in the commit message —
157157ugly but readable. Junio Hamano, the Git maintainer, added another
158158thought: refusing to accept unsigned patches at all.
@@ -172,7 +172,7 @@ On February 8, Kristoffer sent a documentation patch titled "doc: add
172172caveat about roundtripping format-patch" which introduced a new
173173` Documentation/format-patch-caveats.adoc ` file explaining the
174174behavior. The caveat was designed to be included in the documentation
175- for ` git-am ` , ` git-format-patch ` , and ` git-send-email ` .
175+ for git-am(1), git-format-patch(1) , and git-send-email(1) .
176176
177177Junio reviewed
178178[ version 1] ( https://lore.kernel.org/git/format-patch_caveats.281@msgid.xyz )
@@ -186,18 +186,18 @@ flagged that the space after the `---` in the cover letter was
186186inconsistent with the project's conventions.
187187
188188Phillip Wood reviewed the patch and found the mention of
189- ` git-send-email ` a bit distracting, since that command merely runs
190- ` git-format-patch ` and does not do any formatting itself. He also
189+ git-send-email(1) a bit distracting, since that command merely runs
190+ git-format-patch(1) and does not do any formatting itself. He also
191191suggested wording improvements: replacing "One might want to use [ ...]
192192patch(1)" with "Given these limitations, one might be tempted to [ ...] ".
193193
194194Kristoffer incorporated all of this in
195195[ version 2] ( https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz ) ,
196- which dropped the ` git-send-email ` mention from the introductory
196+ which dropped the git-send-email(1) mention from the introductory
197197paragraph (while keeping the CAVEATS section in its documentation, for
198198users who encounter it there), removed example code blocks in favor of
199199clearer prose, and used the list of message-terminating patterns
200- already present in ` git-am ` 's documentation. Junio reviewed it and
200+ already present in git-am(1) 's documentation. Junio reviewed it and
201201queued it with the comment "Nicely written."
202202
203203A third version,
@@ -216,7 +216,7 @@ series titled "commit-msg.sample: reject messages that would confuse
216216 message for unindented ` diff - ` and ` Index: ` lines and reject the
217217 commit with a helpful error message.
2182183 . Added a further check to detect ` --- ` separator lines in the message
219- body, which would cause ` git-am ` to silently truncate the commit
219+ body, which would cause git-am(1) to silently truncate the commit
220220 message.
221221
222222Peff reacted with measured skepticism to patch 3 in
@@ -248,21 +248,21 @@ Kristoffer verified that version 2 worked with `git commit
248248--cleanup=scissors --verbose` and was satisfied.
249249
250250The discussion did not lead to a fundamental fix to the ambiguous
251- parsing in ` git-am ` , which remains an open problem with no obvious
251+ parsing in git-am(1) , which remains an open problem with no obvious
252252backward-compatible solution. But it produced two concrete
253253improvements that were accepted and are now in ` master ` : a CAVEATS
254- section in the documentation for ` git-am ` , ` git-format-patch ` , and
255- ` git-send-email ` spelling out exactly how commit messages can
254+ section in the documentation for git-am(1), git-format-patch(1) , and
255+ git-send-email(1) spelling out exactly how commit messages can
256256inadvertently interfere with patch application, and an enhanced sample
257257` commit-msg ` hook that rejects messages containing unindented diffs.
258258
259259The thread also served as a useful reminder that this problem is not
260260limited to email workflows: any project that generates patches from
261- Git commits using ` git-format-patch ` and applies them with ` patch(1) `
262- or ` git-am ` is exposed to it. The practical advice for authors is
261+ Git commits using git-format-patch(1) and applies them with patch(1)
262+ or git-am(1) is exposed to it. The practical advice for authors is
263263simple: if you include diffs in commit messages for illustrative
264264purposes, make sure to indent them consistently, and be aware that
265- even that does not protect you from ` patch(1) ` .
265+ even that does not protect you from patch(1).
266266
267267## Developer Spotlight: Olamide Caleb Bello
268268
0 commit comments