{"thread":{"id":"64933","subject":"git-am applies commit message diffs","startedAt":"2026-02-06T07:50:03Z","lastAt":"2026-02-14T15:42:56Z","messageCount":65,"participants":["Matthias Beyer","Jacob Keller","Kristoffer Haugsbakk","Florian Weimer","Jeff King","Jakob Haufe","Phillip Wood","Junio C Hamano","kristofferhaugsbakk@fastmail.com","Patrick Steinhardt","Christoph Anton Mitterer"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"535314","messageId":"bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm","threadId":"64933","inReplyTo":null,"subject":"git-am applies commit message diffs","fromName":"Matthias Beyer","fromEmail":"mail@beyermatthias.de","sentAt":"2026-02-06T07:43:56Z","receivedAt":"2026-02-06T07:50:03Z","isPatch":false,"sender":{"key":"mail@beyermatthias.de","avatar":null},"body":"Hi,\n\nI am not sure whether this was already reported, searching the lore did\nnot yield anything for me, but I might have overlooked it...\n\nThis was just posted on mastodon[0]:\n\n    PSA: Did you know that it’s **unsafe** to put code diffs into your commit messages?\n\n    Like https://\n    github.com/i3/i3/pull/6564 for example\n\n    Such diffs will be applied by patch(1) (also git-am(1)) as part of the code change!\n\n    This is how a sleep(1) made it into i3 4.25-2 in Debian unstable.\n\nTL;DR: If you put a diff in the commit message, that diff will be\napplied by git-am.\n\nThis looks clearly like unintended and might be an attack-vector, right?\n\nBest,\nMatthias\n\n[0]: https://mas.to/@zekjur/116022397626943871\n"},{"id":"535320","messageId":"CA+P7+xqcBcV8uySGgDfvt2ruAnFmfgaUy6aRbUC2zCzmCgPubw@mail.gmail.com","threadId":"64933","inReplyTo":"bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm","subject":"Re: git-am applies commit message diffs","fromName":"Jacob Keller","fromEmail":"jacob.keller@gmail.com","sentAt":"2026-02-06T08:04:54Z","receivedAt":"2026-02-06T08:05:04Z","isPatch":false,"sender":{"key":"jacob.keller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"On Thu, Feb 5, 2026 at 11:50 PM Matthias Beyer <mail@beyermatthias.de> wrote:\n>\n> Hi,\n>\n> I am not sure whether this was already reported, searching the lore did\n> not yield anything for me, but I might have overlooked it...\n>\n> This was just posted on mastodon[0]:\n>\n>     PSA: Did you know that it’s **unsafe** to put code diffs into your commit messages?\n>\n>     Like https://\n>     github.com/i3/i3/pull/6564 for example\n>\n>     Such diffs will be applied by patch(1) (also git-am(1)) as part of the code change!\n>\n>     This is how a sleep(1) made it into i3 4.25-2 in Debian unstable.\n>\n> TL;DR: If you put a diff in the commit message, that diff will be\n> applied by git-am.\n>\n> This looks clearly like unintended and might be an attack-vector, right?\n>\n\nIt is certainly surprising. I am not certain I would consider it an\nattack-vector since you should definitely be reading the commit\nmessages before applying, but I could see the fact that its\nunintentional is a problem.\n\nI'm surprised patch would apply since it would likely fail due to\nother non-patch formatted text, no? I suspect this is something that\ncould be handled by using the scissors marker  \"-- >8 --\" in the patch\ndescription to indicate the diff is not part of the patch, or perhaps\nthe splitting of the email should somehow indicate this, for example\nwhen formatting a patch with a diff in it.\n\nI checked by formatting a patch from my own commit message with an\nembedded diff, and there is nothing in place to prevent that diff\nsection from being applied. In practice, I think the advice is \"don't\nput diffs in your commit message\" or \"indent the diff text so that it\nwon't  be parsed as a diff hunk by patch or am.\"\n\nIt seems like a good idea to me to improve the format patch output and\nthe git am patch splitting to somehow try and detect the end of a\nvalid commit message and not treat it as a patch content, but I am\nreally uncertain how to go about doing so safely without risking\nbackwards compatibility (modifying format-patch to insert a marker\nthat properly denotes end of commit would cause issues with older\nversions of git, so we need to use some marker that a well formatted\npatch already does.\n\n> Best,\n> Matthias\n>\n> [0]: https://mas.to/@zekjur/116022397626943871\n"},{"id":"535321","messageId":"hn6q2mdjdqezzvtxfxffmatctnlf4ttvwedfk7wnw7xw75gy4g@hetctv53f7bh","threadId":"64933","inReplyTo":"CA+P7+xqcBcV8uySGgDfvt2ruAnFmfgaUy6aRbUC2zCzmCgPubw@mail.gmail.com","subject":"Re: git-am applies commit message diffs","fromName":"Matthias Beyer","fromEmail":"mail@beyermatthias.de","sentAt":"2026-02-06T08:18:50Z","receivedAt":"2026-02-06T08:18:54Z","isPatch":false,"sender":{"key":"mail@beyermatthias.de","avatar":null},"body":"Hi,\n\nCCing some git-am contributors, hope that's alright for you!\n\nOn Fri, Feb 06, 2026 at 12:04:54AM -0800, Jacob Keller wrote:\n> On Thu, Feb 5, 2026 at 11:50 PM Matthias Beyer <mail@beyermatthias.de> wrote:\n> >\n> > Hi,\n> >\n> > I am not sure whether this was already reported, searching the lore did\n> > not yield anything for me, but I might have overlooked it...\n> >\n> > This was just posted on mastodon[0]:\n> >\n> >     PSA: Did you know that it’s **unsafe** to put code diffs into your commit messages?\n> >\n> >     Like https://\n> >     github.com/i3/i3/pull/6564 for example\n> >\n> >     Such diffs will be applied by patch(1) (also git-am(1)) as part of the code change!\n> >\n> >     This is how a sleep(1) made it into i3 4.25-2 in Debian unstable.\n> >\n> > TL;DR: If you put a diff in the commit message, that diff will be\n> > applied by git-am.\n> >\n> > This looks clearly like unintended and might be an attack-vector, right?\n> >\n> \n> It is certainly surprising. I am not certain I would consider it an\n> attack-vector since you should definitely be reading the commit\n> messages before applying, but I could see the fact that its\n> unintentional is a problem.\n> [...]\n>\n> > [0]: https://mas.to/@zekjur/116022397626943871\n\nAs per the issue linked in that toot I quoted above, the issue clearly\nseems to be that it is not intentional that a diff embedded in the\ncommit message will be applied.\nNobody ever guessed that and that `sleep 1` that was in the commit\nmessage made it into debian unstable because people assumed it to work\nas intended.\n\nI call that sheer luck, that it was only a `sleep 1` and not a \"here is\nhow I made this into a backdoor and here is a patch to fix it\",\nultimately getting the backdoor in which was written as a diff in the\ncommit message, instead of the \"fix\" in the \"patch part\" of the email.\n\n\nThat said, I am no expert in either C or the git codebase at all, but\nfrom what I saw from reading the git-am codebase, it looks like it tries\nto find the patch by looking for three dashes on a line with a linebreak\nbehind (\"---\\n\").\nFrom what I read, it looks for that from the first line.\nWhat I would think of here is looking for that \"patchbreak\" from the\n_end_ of the email rather than from the top, that would have prevented\nthis issue, right?\n\nBest,\nMatthias\n"},{"id":"535322","messageId":"1b1f8959-aa11-4bce-8535-7245c8567d6a@app.fastmail.com","threadId":"64933","inReplyTo":"bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm","subject":"Re: git-am applies commit message diffs","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-06T08:43:04Z","receivedAt":"2026-02-06T08:44:21Z","isPatch":false,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Fri, Feb 6, 2026, at 08:43, Matthias Beyer wrote:\n> Hi,\n>\n> I am not sure whether this was already reported, searching the lore did\n> not yield anything for me, but I might have overlooked it...\n>\n> This was just posted on mastodon[0]:\n>\n>     PSA: Did you know that it’s **unsafe** to put code diffs into your\n> commit messages?\n>\n>     Like https://\n>     github.com/i3/i3/pull/6564 for example\n>\n>     Such diffs will be applied by patch(1) (also git-am(1)) as part of\n> the code change!\n>\n>     This is how a sleep(1) made it into i3 4.25-2 in Debian unstable.\n>\n> TL;DR: If you put a diff in the commit message, that diff will be\n> applied by git-am.\n>\n> This looks clearly like unintended and might be an attack-vector, right?\n\nRelated: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n\nBut for the magic string that git-format-patch(1) uses at the start of\neach email.\n\nLike Jacob said the cure is to use indentation for code blocks.\n\nhttps://lore.kernel.org/git/xmqqttcmv8a6.fsf@gitster.g/#t\n\nIndentation for code blocks: just stylistic until it isn’t. ;-)\n"},{"id":"535323","messageId":"lhutsvuuu18.fsf@oldenburg.str.redhat.com","threadId":"64933","inReplyTo":"CA+P7+xqcBcV8uySGgDfvt2ruAnFmfgaUy6aRbUC2zCzmCgPubw@mail.gmail.com","subject":"Re: git-am applies commit message diffs","fromName":"Florian Weimer","fromEmail":"fweimer@redhat.com","sentAt":"2026-02-06T08:59:31Z","receivedAt":"2026-02-06T08:59:39Z","isPatch":false,"sender":{"key":"fweimer@redhat.com","avatar":null},"body":"* Jacob Keller:\n\n> It seems like a good idea to me to improve the format patch output and\n> the git am patch splitting to somehow try and detect the end of a\n> valid commit message and not treat it as a patch content, but I am\n> really uncertain how to go about doing so safely without risking\n> backwards compatibility (modifying format-patch to insert a marker\n> that properly denotes end of commit would cause issues with older\n> versions of git, so we need to use some marker that a well formatted\n> patch already does.\n\nIsn't the format-patch output already unambiguous because the sequence\nof diffs is preceeded by the non-diff statistics section, and only then\nthe commit message follows?  It's just not possible to process this\ncorrectly in one pass because only at the end of the input, you know\nthat you have just seen the to-be-applied diffs.\n\nThe other tool to look at is git rebase.  There have been problems with\nthe lack of \"From \" encoding in commit messages in the past, which\ncaused rebases to fail due to commit message contents (but I can totally\nimagine that this might have resulted in commit injection with more\ncarefully crafted commit messages).\n\nThanks,\nFlorian\n\n"},{"id":"535324","messageId":"20260206090358.GA2761602@coredump.intra.peff.net","threadId":"64933","inReplyTo":"hn6q2mdjdqezzvtxfxffmatctnlf4ttvwedfk7wnw7xw75gy4g@hetctv53f7bh","subject":"Re: git-am applies commit message diffs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-06T09:03:58Z","receivedAt":"2026-02-06T09:04:05Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 06, 2026 at 09:18:50AM +0100, Matthias Beyer wrote:\n\n> That said, I am no expert in either C or the git codebase at all, but\n> from what I saw from reading the git-am codebase, it looks like it tries\n> to find the patch by looking for three dashes on a line with a linebreak\n> behind (\"---\\n\").\n\nYes, that is how the split is made.\n\n> From what I read, it looks for that from the first line.\n> What I would think of here is looking for that \"patchbreak\" from the\n> _end_ of the email rather than from the top, that would have prevented\n> this issue, right?\n\nThe patch itself may legitimately contain \"---\" on a line by itself (it\nwould indicate that the line \"--\" was removed from a file). That would\nconfuse your parser, including in a way that we end up only applying\npart of the diff (everything before that fake \"---\" becomes commit\nmessage, and everything after becomes cover-letter material up to the\nnext \"diff\" line).\n\nI suspect it also creates corner cases with cover-letter material\n(between the \"---\" and the diff itself) that itself contains any \"---\"\nmarker.\n\nI don't think there is a way to unambiguously parse the single-stream\noutput that format-patch produces. This is a reasonably well-known\ngotcha (at least around here). E.g., some earlier discussions:\n\n  2024: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n  2022: https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n  2015: https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n\nThere are probably more, but it's actually a tricky thing to search for\nin the archive, so I stopped digging. ;)\n\nI think the general attitude has been that such things are a nuisance\nwhen you trigger them accidentally, but probably an unlikely security\nissue if we assume a human is reading the patch (and if they're not, all\nbets are off anyway).\n\nIronically, you can ask format-patch to split the message and patch\nusing the \"--attach\" option, which should be unambiguous (they are in\ntwo mime parts). But git-mailinfo (which powers git-am under the hood)\ndecodes the two parts into a single stream, and still takes a \"diff\"\nline in the commit message part as the start of the diff.\n\nArguably that could be improved, but I suspect might break other cases\n(I think it is trying to be forgiving to folks who have shoved the whole\npatch into an attachment). So you'd have to pull the attachments apart\nyourself and feed them individually to \"git apply\" and \"git commit -F\".\n\n-Peff\n"},{"id":"535326","messageId":"20260206092423.GB2761602@coredump.intra.peff.net","threadId":"64933","inReplyTo":"lhutsvuuu18.fsf@oldenburg.str.redhat.com","subject":"Re: git-am applies commit message diffs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-06T09:24:23Z","receivedAt":"2026-02-06T09:24:25Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 06, 2026 at 09:59:31AM +0100, Florian Weimer wrote:\n\n> Isn't the format-patch output already unambiguous because the sequence\n> of diffs is preceeded by the non-diff statistics section, and only then\n> the commit message follows?  It's just not possible to process this\n> correctly in one pass because only at the end of the input, you know\n> that you have just seen the to-be-applied diffs.\n\nThat diffstat is optional, and not parsed by the receiving format-patch\nat all. Keep in mind that in the world for which it was originally\ndesigned, people were not necessarily using Git to generate their\nemails. They could be patches emailed by random folks using \"diff\"\nthemselves.\n\n> The other tool to look at is git rebase.  There have been problems with\n> the lack of \"From \" encoding in commit messages in the past, which\n> caused rebases to fail due to commit message contents (but I can totally\n> imagine that this might have resulted in commit injection with more\n> carefully crafted commit messages).\n\nIt has been a long time since I looked at it, but IIRC we did have a\nproblem with fidelity of commit message in git-rebase, since it was\nbased on a format-patch/am pipeline. And we solved it by teaching \"git\nam\" a magic \"--rebasing\" flag which tells it to ignore the email\ncontents and find the actual commit in the object database. Gross, but\nit works. But of course the same does not work for a true emailed patch,\nsince the point is that the receiver does not have the commit object\nyet.\n\n-Peff\n"},{"id":"535329","messageId":"lhujywqtd76.fsf@oldenburg.str.redhat.com","threadId":"64933","inReplyTo":"20260206092423.GB2761602@coredump.intra.peff.net","subject":"Re: git-am applies commit message diffs","fromName":"Florian Weimer","fromEmail":"fweimer@redhat.com","sentAt":"2026-02-06T09:48:29Z","receivedAt":"2026-02-06T09:48:38Z","isPatch":false,"sender":{"key":"fweimer@redhat.com","avatar":null},"body":"* Jeff King:\n\n> On Fri, Feb 06, 2026 at 09:59:31AM +0100, Florian Weimer wrote:\n>\n>> Isn't the format-patch output already unambiguous because the sequence\n>> of diffs is preceeded by the non-diff statistics section, and only then\n>> the commit message follows?  It's just not possible to process this\n>> correctly in one pass because only at the end of the input, you know\n>> that you have just seen the to-be-applied diffs.\n>\n> That diffstat is optional, and not parsed by the receiving format-patch\n> at all. Keep in mind that in the world for which it was originally\n> designed, people were not necessarily using Git to generate their\n> emails. They could be patches emailed by random folks using \"diff\"\n> themselves.\n\nIs the git am format that flexible in practice?  I often have trouble\napplying patches with git am that were created with git format-patch\nand have to resort to plain old patch instead.  As a user, I definitely\nget the impression that it's not a type of tool that gets a patch\nout of an email message, no matter what the cost.\n\nThanks,\nFlorian\n\n"},{"id":"535330","messageId":"20260206100837.GA2778409@coredump.intra.peff.net","threadId":"64933","inReplyTo":"lhujywqtd76.fsf@oldenburg.str.redhat.com","subject":"Re: git-am applies commit message diffs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-06T10:08:37Z","receivedAt":"2026-02-06T10:08:39Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 06, 2026 at 10:48:29AM +0100, Florian Weimer wrote:\n\n> > On Fri, Feb 06, 2026 at 09:59:31AM +0100, Florian Weimer wrote:\n> >\n> >> Isn't the format-patch output already unambiguous because the sequence\n> >> of diffs is preceeded by the non-diff statistics section, and only then\n> >> the commit message follows?  It's just not possible to process this\n> >> correctly in one pass because only at the end of the input, you know\n> >> that you have just seen the to-be-applied diffs.\n> >\n> > That diffstat is optional, and not parsed by the receiving format-patch\n> > at all. Keep in mind that in the world for which it was originally\n> > designed, people were not necessarily using Git to generate their\n> > emails. They could be patches emailed by random folks using \"diff\"\n> > themselves.\n> \n> Is the git am format that flexible in practice?  I often have trouble\n> applying patches with git am that were created with git format-patch\n> and have to resort to plain old patch instead.  As a user, I definitely\n> get the impression that it's not a type of tool that gets a patch\n> out of an email message, no matter what the cost.\n\nI'm sure there are corner cases it doesn't handle, but it will take\ninput like this:\n\ngit am <<\\EOF\nFrom: Jeff King <peff@peff.net>\nDate: Fri Feb 6 03:42:12 2026 -0500\nSubject: my cool patch\n\nthis fixes some stuff\n\ndiff -Nru old/file new/file\n--- old/file\t2026-02-06 04:58:56.148348259 -0500\n+++ new/file\t2026-02-06 04:58:59.432360938 -0500\n@@ -1 +1 @@\n-base\n+changed\nEOF\n\n\nand happily produce the commit you'd expect. I generated the diff there\nwith GNU diff, and typed the rest. Likewise for this version with\nattachments, which I generated with mutt:\n\ngit am <<\\EOF\nDate: Fri, 6 Feb 2026 05:03:31 -0500\nFrom: Jeff King <peff@peff.net>\nTo: Jeff King <peff@peff.net>\nSubject: my cool patch\nMIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"tveeCB9LAhLXuhMJ\"\nContent-Disposition: inline\n\n\n--tveeCB9LAhLXuhMJ\nContent-Type: text/plain; charset=utf-8\nContent-Disposition: inline\n\nsee the attached patch, which does blah blah blah\n\n--tveeCB9LAhLXuhMJ\nContent-Type: text/plain; charset=utf-8\nContent-Disposition: attachment; filename=patch\n\ndiff -Nru old/file new/file\n--- old/file\t2026-02-06 04:58:56.148348259 -0500\n+++ new/file\t2026-02-06 04:58:59.432360938 -0500\n@@ -1 +1 @@\n-base\n+changed\n\n--tveeCB9LAhLXuhMJ--\nEOF\n\n\nI expect that Linus saw a lot of this kind of stuff in the early days.\nI'd guess it's pretty rare now, but I won't be surprised if there are\nsome die-hards generating kernel patches with who-knows-what. ;)\n\n-Peff\n"},{"id":"535374","messageId":"20260206184508.5a014df2@beer","threadId":"64933","inReplyTo":"1b1f8959-aa11-4bce-8535-7245c8567d6a@app.fastmail.com","subject":"Re: git-am applies commit message diffs","fromName":"Jakob Haufe","fromEmail":"sur5r@sur5r.net","sentAt":"2026-02-06T17:45:08Z","receivedAt":"2026-02-06T17:51:09Z","isPatch":false,"sender":{"key":"sur5r@sur5r.net","avatar":null},"body":"On Fri, 06 Feb 2026 09:43:04 +0100\n\"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> wrote:\n\n> Like Jacob said the cure is to use indentation for code blocks.\n\nThat doesn't help here as stated by Michael on GH and his Mastodon\npost. Also, to make sure this doesn't get lost:\n\nFrom patch(1):\n\n---\nIf the entire diff is indented by a consistent amount, if lines end in CRLF,\nor if a diff is encapsulated one or more times by prepending \"- \" to lines\nstarting with \"-\" as specified by Internet RFC 934, this is taken into account.\nAfter removing indenting or encapsulation, lines beginning with # are ignored,\nas they are considered to be comments.\n---\n\nIt's not exactly written in a straightforward way, but it show that the\nbehavior from patch is intentional. So even if git-am gets a fix, it\nonly partly mitigates the problem as I'm pretty sure I will not be the\nlast one to pass \"git show\"/\"git format-patch\" to \"patch\".\n\nCheers,\nsur5r\n\n-- \nceterum censeo microsoftem esse delendam.\n"},{"id":"535410","messageId":"f6e4cdb4-ff82-4853-aca5-0c152f287286@app.fastmail.com","threadId":"64933","inReplyTo":"20260206184508.5a014df2@beer","subject":"Re: git-am applies commit message diffs","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T10:08:29Z","receivedAt":"2026-02-07T10:08:50Z","isPatch":false,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Fri, Feb 6, 2026, at 18:45, Jakob Haufe wrote:\n> On Fri, 06 Feb 2026 09:43:04 +0100\n> \"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> wrote:\n>\n>> Like Jacob said the cure is to use indentation for code blocks.\n>\n> That doesn't help here as stated by Michael on GH and his Mastodon\n> post. Also, to make sure this doesn't get lost:\n>\n> From patch(1):\n>\n> ---\n> If the entire diff is indented by a consistent amount, if lines end in CRLF,\n> or if a diff is encapsulated one or more times by prepending \"- \" to lines\n> starting with \"-\" as specified by Internet RFC 934, this is taken into account.\n> After removing indenting or encapsulation, lines beginning with # are ignored,\n> as they are considered to be comments.\n> ---\n\nYeah, I think I understand now.\n\n• patch(1) will apply all the diffs from git-format-patch(1), including\n  from the commit message\n• git-am(1) will do the same\n• git-am(1) will do the expected thing if you indent the diff in the\n  commit message\n• For the git-format-patch(1) output with an indented diff in the commit\n  message: `git patch -p1` (I guess to strip the `a/` and `b/` from\n  git(1) diffs?) applies everything, including the `sleep(1)`[1]\n\nMy hodgepodge assumptions from 2024[2] were off. I thought that as long\nas you did the following:\n\n• Do not put the magic `From` string at the start of any line in the\n  commit message\n• Do not put `---` at the start of the line in the commit message\n• Do not put diff output unindented in the commit message since\n  git-am(1) will think that is the diff and not care about finding any\n  `–––`[3]\n\nThen git-am(1) would apply the commit message and the diff part as\nexpected.\n\n† 1: Related is https://github.com/i3/i3/pull/6564#issuecomment-3863278059 ,\n     specifically the link https://lists.gnu.org/archive/html/bug-patch/2026-02/msg00000.html\n[2]: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n† 3: And my assumption here that only the diff in the commit message\n     would be applied in this case was wrong. Or else it would have been\n     more immediately obvious that the resulting commit was wrong.\n\n> It's not exactly written in a straightforward way,\n\nYeah it’s not straightforward at all.\n\nSomething useful might be to apply all patches if they are all at the\nsame indentation level. I don’t see how it is useful to apparently strip\nall indentation and find all the diffs that way.\n\n> but it show that the behavior from patch is intentional. So even if\n> git-am gets a fix, it only partly mitigates the problem as I'm pretty\n> sure I will not be the last one to pass \"git show\"/\"git format-patch\"\n> to \"patch\".\n\nI don’t pass output from git(1) to patch(1). But I have often (like the\nhandful of times I’ve needed it) fallen back on using patch(1) for\npatches/diffs that are thrown into email messages since it is more\nforgiving than git-apply(1), and I guess also git-am(1).\n\nThe diff in the commit message doesn’t have the trailing whitespace that\nI thought would be needed for patch application. Since git-commit(1) by\ndefault cleans up trailing whitespace. But apparently patch(1) is fine\nwith that.\n"},{"id":"535415","messageId":"cover.1770476279.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"20260206090358.GA2761602@coredump.intra.peff.net","subject":"[PATCH 0/3] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-07T14:57:59Z","receivedAt":"2026-02-07T14:58:23Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nOn 06/02/2026 09:03, Jeff King wrote:\n> I don't think there is a way to unambiguously parse the single-stream\n> output that format-patch produces. This is a reasonably well-known\n> gotcha (at least around here). E.g., some earlier discussions:\n>\n>    2024:https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n>    2022:https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n>    2015:https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n\nIf we cannot improve \"git am\" perhaps we should update our sample\n\"commit-msg\" hook to reject messages that will cause problems. Here\nare some patches to do that.\n\nWe could perhaps think about adding a more prominent warning to the\n\"git am\" and \"git format-patch\" documentation. The docs for \"git am\"\nmention that it splits the message on a line starting with \"diff -\"\nbut maybe we should spell out what that means for commit messages that\ninclude a diff. In principle \"git format-patch\" could also warn or\nerror out if it creates a mail that \"git am\" cannot import verbatim,\nI don't know how hard that would be in implement.\n\nBase-Commit: b2826b52eb7caff9f4ed6e85ec45e338bf02ad09\nPublished-As: https://github.com/phillipwood/git/releases/tag/pw%2Fsample-commit-msg-reject-diff%2Fv1\nView-Changes-At: https://github.com/phillipwood/git/compare/b2826b52e...83c100a73\nFetch-It-Via: git fetch https://github.com/phillipwood/git pw/sample-commit-msg-reject-diff/v1\n\n\nPhillip Wood (3):\n  templates: add .gitattributes entry for sample hooks\n  templates: detect commit messages containing diffs\n  templates: detect messages that contain a separator line\n\n .editorconfig                     |  2 +-\n .gitattributes                    |  1 +\n templates/hooks/commit-msg.sample | 38 +++++++++++++++++++++++++++++--\n 3 files changed, 38 insertions(+), 3 deletions(-)\n\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535416","messageId":"5f5e30914355ba108d8f4ce9157369e979f585e4.1770476279.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"cover.1770476279.git.phillip.wood@dunelm.org.uk","subject":"[PATCH 1/3] templates: add .gitattributes entry for sample hooks","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-07T14:58:00Z","receivedAt":"2026-02-07T14:58:24Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThe sample hooks are shell scripts but the filenames end with \".sample\"\nso they need their own .gitattributes rule. Update our editorconfig\nsettings to match the attributes as well.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n .editorconfig  | 2 +-\n .gitattributes | 1 +\n 2 files changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/.editorconfig b/.editorconfig\nindex 2d3929b5916..6e4eaa8e955 100644\n--- a/.editorconfig\n+++ b/.editorconfig\n@@ -4,7 +4,7 @@ insert_final_newline = true\n \n # The settings for C (*.c and *.h) files are mirrored in .clang-format.  Keep\n # them in sync.\n-[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile}]\n+[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile,templates/hooks/*.sample}]\n indent_style = tab\n tab_width = 8\n \ndiff --git a/.gitattributes b/.gitattributes\nindex 38b1c52fe0e..556322be01b 100644\n--- a/.gitattributes\n+++ b/.gitattributes\n@@ -18,3 +18,4 @@ CODE_OF_CONDUCT.md -whitespace\n /Documentation/user-manual.adoc conflict-marker-size=32\n /t/t????-*.sh conflict-marker-size=32\n /t/unit-tests/clar/test/expected/* whitespace=-blank-at-eof\n+/templates/hooks/*.sample whitespace=indent,trail,space,incomplete text eol=lf\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535417","messageId":"e75978b959157ddc235465b3cf5cf95aaf3d75ff.1770476279.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"cover.1770476279.git.phillip.wood@dunelm.org.uk","subject":"[PATCH 2/3] templates: detect commit messages containing diffs","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-07T14:58:01Z","receivedAt":"2026-02-07T14:58:25Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nIf a commit message contains a diff that is not indented then \"git\nam\" will treat that diff as part of the patch rather than as part\nof the commit message. This allows it to apply email messages that\nwere created by adding a commit message in front of a regular diff\nwithout adding the \"---\" separator used by \"git format-patch\". This\noften surprises users [1-4] so add a check to the sample \"commit-msg\"\nhook to reject messages that would confuse \"git am\".\n\nDetecting if the message contains a diff is complicated by the hook\nbeing passed the message before it is cleaned up so we need to ignore\nany diffs below the scissors line. There are also two possible\nconfig keys to check to find the comment character at the start\nof the scissors line.\n\n[1] https://lore.kernel.org/git/bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm\n[2] https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n[3] https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n[4] https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n templates/hooks/commit-msg.sample | 31 +++++++++++++++++++++++++++++--\n 1 file changed, 29 insertions(+), 2 deletions(-)\n\ndiff --git a/templates/hooks/commit-msg.sample b/templates/hooks/commit-msg.sample\nindex b58d1184a9d..099cc58c303 100755\n--- a/templates/hooks/commit-msg.sample\n+++ b/templates/hooks/commit-msg.sample\n@@ -15,10 +15,37 @@\n # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n # grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n \n-# This example catches duplicate Signed-off-by lines.\n+# This example catches duplicate Signed-off-by lines and messages that\n+# would confuse 'git am'.\n+\n+ret=0\n \n test \"\" = \"$(grep '^Signed-off-by: ' \"$1\" |\n \t sort | uniq -c | sed -e '/^[ \t]*1[ \t]/d')\" || {\n \techo >&2 Duplicate Signed-off-by lines.\n-\texit 1\n+\tret=1\n }\n+\n+comment_re=\"$(\n+\t{\n+\t\tgit config --get-regexp \"^core\\.comment(char|string)\\$\" ||\n+\t\t\techo '#'\n+\t} | sed -n -e '\n+\t\t${\n+\t\t\ts/^[^ ]* //\n+\t\t\ts|[][*./\\]|\\\\&|g\n+\t\t\ts/^auto$/[#;@!$%^&|:]/\n+\t\t\tp\n+\t\t}'\n+)\"\n+line=\"$(sed -n -e \"/^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$/q\n+\t\t   /^diff -/{p;q;}\n+\t\t   /^Index: /{p;q;}\" \"$1\")\"\n+if test -n \"$line\"\n+then\n+\techo >&2 \"Message contains a diff that will confuse 'git am'.\"\n+\techo >&2 \"To fix this indent the diff.\"\n+\tret=1\n+fi\n+\n+exit $ret\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535418","messageId":"83c100a73ec722bf72a15b7b40b0c82bf8829168.1770476279.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"cover.1770476279.git.phillip.wood@dunelm.org.uk","subject":"[PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-07T14:58:02Z","receivedAt":"2026-02-07T14:58:26Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nMessages that contain \"---\" separator lines will be truncated by\n\"git am\". This often surprises users so add a check to the sample\n\"commit-msg\" hook to reject such messages. As it's conceivable that\nsomeone is using \"---\" as their comment string we delete any commented\nlines before checking for a separator. The trailing \".*\" when matching\ncommented lines ensures that if the comment string ends with a \"$\"\nit is not treated as an anchor.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n templates/hooks/commit-msg.sample | 9 ++++++++-\n 1 file changed, 8 insertions(+), 1 deletion(-)\n\ndiff --git a/templates/hooks/commit-msg.sample b/templates/hooks/commit-msg.sample\nindex 099cc58c303..c7a9db88cb9 100755\n--- a/templates/hooks/commit-msg.sample\n+++ b/templates/hooks/commit-msg.sample\n@@ -39,9 +39,16 @@ comment_re=\"$(\n \t\t}'\n )\"\n line=\"$(sed -n -e \"/^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$/q\n+\t\t   /^${comment_re}.*/d\n+\t\t   /^---\\$/{p;q;}\n \t\t   /^diff -/{p;q;}\n \t\t   /^Index: /{p;q;}\" \"$1\")\"\n-if test -n \"$line\"\n+if test \"$line\" = \"---\"\n+then\n+\techo >&2 \"Message contains a '---' separator line that will confuse\"\n+\techo >&2 \"'git am'. To fix this indent the '---' line.\"\n+\tret=1\n+elif test -n \"$line\"\n then\n \techo >&2 \"Message contains a diff that will confuse 'git am'.\"\n \techo >&2 \"To fix this indent the diff.\"\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535443","messageId":"xmqqldh4b5y2.fsf@gitster.g","threadId":"64933","inReplyTo":"83c100a73ec722bf72a15b7b40b0c82bf8829168.1770476279.git.phillip.wood@dunelm.org.uk","subject":"Re: [PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-07T21:27:01Z","receivedAt":"2026-02-07T21:27:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Messages that contain \"---\" separator lines will be truncated by\n> \"git am\". This often surprises users so add a check to the sample\n> \"commit-msg\" hook to reject such messages. As it's conceivable that\n> someone is using \"---\" as their comment string we delete any commented\n> lines before checking for a separator. The trailing \".*\" when matching\n> commented lines ensures that if the comment string ends with a \"$\"\n> it is not treated as an anchor.\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  templates/hooks/commit-msg.sample | 9 ++++++++-\n>  1 file changed, 8 insertions(+), 1 deletion(-)\n\nI have no qualms about the topic up to the previous step, but I know\none of the things that I sometimes do will be broken with the change\nin this step, namely, when I know what I want to write below the\nthree-dash lines, I would commit with \"---\" and additional notes\nbelow it, so that I do not forget during \"format-patch\".\n\nWhen the commit is turned into a patch email, possibly with some\nother material like \"--notes=<ref>\" that adds notes there, the\nresulting message will have two three-dashes lines, but because \"am\"\ncuts at the first one, and \"apply\" knows that the garbage lines at\nfront, including three-dash lines, do not matter until it sees \"^diff\",\nthis works out perfectly well.\n\nAdmittedly, I myself do not send out so many patches as I used to,\nbut I suspect that there are others who have discovered this trick\nindependently, and they would be unhappy to be interrupted by\ncommit-msg hook like this.\n\nA saving grace is that when the user is stopped with this,\npre-commit hook that inspects the contents to be committed\nhave already run successfully, so rerunning with \"--no-verify\"\nis not with too much risk.  But still, I am not sure if this is a\ngood thing to do overall.\n\n> diff --git a/templates/hooks/commit-msg.sample b/templates/hooks/commit-msg.sample\n> index 099cc58c303..c7a9db88cb9 100755\n> --- a/templates/hooks/commit-msg.sample\n> +++ b/templates/hooks/commit-msg.sample\n> @@ -39,9 +39,16 @@ comment_re=\"$(\n>  \t\t}'\n>  )\"\n>  line=\"$(sed -n -e \"/^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$/q\n> +\t\t   /^${comment_re}.*/d\n> +\t\t   /^---\\$/{p;q;}\n>  \t\t   /^diff -/{p;q;}\n>  \t\t   /^Index: /{p;q;}\" \"$1\")\"\n> -if test -n \"$line\"\n> +if test \"$line\" = \"---\"\n> +then\n> +\techo >&2 \"Message contains a '---' separator line that will confuse\"\n> +\techo >&2 \"'git am'. To fix this indent the '---' line.\"\n> +\tret=1\n> +elif test -n \"$line\"\n>  then\n>  \techo >&2 \"Message contains a diff that will confuse 'git am'.\"\n>  \techo >&2 \"To fix this indent the diff.\"\n"},{"id":"535445","messageId":"32614598-48f0-4e3d-ba8c-e8d96b71dbd9@app.fastmail.com","threadId":"64933","inReplyTo":"xmqqldh4b5y2.fsf@gitster.g","subject":"Re: [PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T21:38:10Z","receivedAt":"2026-02-07T21:38:31Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Sat, Feb 7, 2026, at 22:27, Junio C Hamano wrote:\n>>[snip]\n>\n> I have no qualms about the topic up to the previous step, but I know\n> one of the things that I sometimes do will be broken with the change\n> in this step, namely, when I know what I want to write below the\n> three-dash lines, I would commit with \"---\" and additional notes\n> below it, so that I do not forget during \"format-patch\".\n>\n> When the commit is turned into a patch email, possibly with some\n> other material like \"--notes=<ref>\" that adds notes there, the\n> resulting message will have two three-dashes lines, but because \"am\"\n> cuts at the first one, and \"apply\" knows that the garbage lines at\n> front, including three-dash lines, do not matter until it sees \"^diff\",\n> this works out perfectly well.\n>\n> Admittedly, I myself do not send out so many patches as I used to,\n> but I suspect that there are others who have discovered this trick\n> independently, and they would be unhappy to be interrupted by\n> commit-msg hook like this.\n>\n> A saving grace is that when the user is stopped with this,\n> pre-commit hook that inspects the contents to be committed\n> have already run successfully, so rerunning with \"--no-verify\"\n> is not with too much risk.  But still, I am not sure if this is a\n> good thing to do overall.\n\nMaybe this is not the right tool[1] but perhaps the hook could respect\nan env. variable to disable this check and hint about it in the error\noutput?\n\n🔗 1: https://lore.kernel.org/git/cover.1709495964.git.code@khaugsbakk.name/\n"},{"id":"535448","messageId":"2dc92f55-c252-43db-a412-342fc8d45e4c@app.fastmail.com","threadId":"64933","inReplyTo":"bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm","subject":"Re: git-am applies commit message diffs","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T21:44:31Z","receivedAt":"2026-02-07T21:44:53Z","isPatch":false,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Fri, Feb 6, 2026, at 08:43, Matthias Beyer wrote:\n> Hi,\n>\n> I am not sure whether this was already reported, searching the lore did\n> not yield anything for me, but I might have overlooked it...\n>\n> This was just posted on mastodon[0]:\n>\n>     PSA: Did you know that it’s **unsafe** to put code diffs into your\n> commit messages?\n>\n>     Like https://\n>     github.com/i3/i3/pull/6564 for example\n>\n>     Such diffs will be applied by patch(1) (also git-am(1)) as part of\n> the code change!\n>\n>     This is how a sleep(1) made it into i3 4.25-2 in Debian unstable.\n>\n> TL;DR: If you put a diff in the commit message, that diff will be\n> applied by git-am.\n>\n> This looks clearly like unintended and might be an attack-vector, right?\n\nI have an idea for a proposal to note this in the documentation.\n"},{"id":"535454","messageId":"format-patch_caveats.281@msgid.xyz","threadId":"64933","inReplyTo":"bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm","subject":"[PATCH] doc: add caveat about roundtripping format-patch","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-08T00:11:17Z","receivedAt":"2026-02-08T00:11:50Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\ngit-format-patch(1), git-send-email(1), and git-am(1) deal with\nformatting commits as patches, sending them (perhaps directly), and\napplying them, respectively. Naturally they use a few delimiters to mark\nwhere the commit message ends. This can lead to surprising behavior when\nthese delimiters are used in the commit message itself.\n\ngit-format-patch(1) and git-send-email(1) will accept any commit message\nand not warn or error about these delimiters being used.[1]\n\nMoreover, the presence of unindented diffs in the commit message will\ncause git-am(1) to apply both the diffs from the commit message as well\nas the patch section.[2]\n\nIt is unclear whether any commands in this chain will learn to warn\nabout this. One concern could be that users have learned to rely on\nthe three-dash line rule to conveniently add extra-commit message\ninformation in the commit message, knowing that git-am(1) will\nignore it.[4]\n\nAll of this is covered already, technically, However, we should spell\nout the implications.\n\n† 1: There is also git-commit(1) to consider. However, making that\n     command warn or error out over such delimiters would be disruptive\n     to all Git users who never use email in their workflow.\n[2]: Recently patch(1) caused this issue for a project, but it was noted\n     that git-am(1) has the same behavior[3]\n[3]: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n[4]: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n\nReported-by: Matthias Beyer <mail@beyermatthias.de>\nReported-by: Christoph Anton Mitterer <calestyo@scientia.org>\nReported-by: Matheus Tavares <matheus.tavb@gmail.com>\nReported-by: Chris Packham <judge.packham@gmail.com>\nHelped-by: Jakob Haufe <sur5r@sur5r.net>\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n\nNotes (series):\n    There might be other things to do here. Mention it in gitfaq(5)?\n    \n    § Trailers\n    \n    • Reported-by: Matthias Beyer <mail@beyermatthias.de>\n      • From this thread\n    Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n      • From https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/T/#u\n    Reported-by: Matheus Tavares <matheus.bernardino@usp.br>\n      • From https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/#t\n    Reported-by: Chris Packham <judge.packham@gmail.com>\n      • From https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n    \n    (These were all linked in https://lore.kernel.org/git/20260206090358.GA2761602@coredump.intra.peff.net/ )\n    \n    Helped-by: Jakob Haufe <sur5r@sur5r.net>\n      • For the part about patch(1): https://lore.kernel.org/git/f6e4cdb4-ff82-4853-aca5-0c152f287286@app.fastmail.com/T/#mc389dbd2ae02a007cbe57cd16ca4790ecc5a84f7\n\n Documentation/format-patch-caveats.adoc | 39 +++++++++++++++++++++++++\n Documentation/git-am.adoc               |  9 ++++++\n Documentation/git-format-patch.adoc     |  4 +++\n Documentation/git-send-email.adoc       |  5 ++++\n 4 files changed, 57 insertions(+)\n create mode 100644 Documentation/format-patch-caveats.adoc\n\ndiff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\nnew file mode 100644\nindex 00000000000..2accf2763fd\n--- /dev/null\n+++ b/Documentation/format-patch-caveats.adoc\n@@ -0,0 +1,39 @@\n+Patches produced by linkgit:git-format-patch[1] or\n+linkgit:git-send-email[1] are inline. This means that the output of\n+these two commands can lead to a different commit message when applied\n+with linkgit:git-am[1]. It can also mean that the patch is not applied\n+correctly.\n+\n+The commit message might contain a three-dash line (`---`) which was\n+perhaps meant to be a thematic break. That means that the commit message\n+will be cut short. The presence of a line starting with \"Index: \" can\n+cause the patch not to be found, giving an error about an empty patch.\n+\n+Furthermore, the presence of an unindented diff in the commit message\n+will not only cut the message short but cause that very diff to be\n+applied, along with the patch in the patch section. The commit message\n+might for example have a diff in a GitHub MarkDown code fence:\n+\n+----\n+```\n+diff ...\n+```\n+----\n+\n+The solution for this is to indent the diff instead:\n+\n+----\n+    diff ...\n+----\n+\n+This loss of fidelity might be simple to notice if you are applying\n+patches directly from a mailbox. However, a commit authored long ago\n+might be applied in a different context, perhaps because many changes\n+are being integrated via patch files and the\n+linkgit:git-format-patch[1] format is trusted to import changes of a\n+Git origin.\n+\n+One might want to use a general-purpose utility like patch(1) instead,\n+given these limitations. However, patch(1) will not only look for\n+unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n+diffs as well.\ndiff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\nindex 0c94776e296..18f5b950825 100644\n--- a/Documentation/git-am.adoc\n+++ b/Documentation/git-am.adoc\n@@ -259,10 +259,13 @@ message.  Any line that is of the form:\n * a line that begins with \"Index: \"\n \n is taken as the beginning of a patch, and the commit log message\n is terminated before the first occurrence of such a line.\n \n+This means that the content of the commit message can inadverently\n+interrupt the processing (see the <<caveats,CAVEATS>> section below).\n+\n When initially invoking `git am`, you give it the names of the mailboxes\n to process.  Upon seeing the first patch that does not apply, it\n aborts in the middle.  You can recover from this in one of two ways:\n \n . skip the current patch by re-running the command with the `--skip`\n@@ -281,10 +284,16 @@ Before any patches are applied, ORIG_HEAD is set to the tip of the\n current branch.  This is useful if you have problems with multiple\n commits, like running 'git am' on the wrong branch or an error in the\n commits that is more easily fixed by changing the mailbox (e.g.\n errors in the \"From:\" lines).\n \n+[[caveats]]\n+CAVEATS\n+-------\n+\n+include::format-patch-caveats.adoc[]\n+\n HOOKS\n -----\n This command can run `applypatch-msg`, `pre-applypatch`,\n and `post-applypatch` hooks.  See linkgit:githooks[5] for more\n information.\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 9a7807ca71a..36851aaf5e1 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -796,10 +796,14 @@ CAVEATS\n Note that `format-patch` will omit merge commits from the output, even\n if they are part of the requested range. A simple \"patch\" does not\n include enough information for the receiving end to reproduce the same\n merge commit.\n \n+'''\n+\n+include::format-patch-caveats.adoc[]\n+\n SEE ALSO\n --------\n linkgit:git-am[1], linkgit:git-send-email[1]\n \n GIT\ndiff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc\nindex ebe8853e9f5..0b118df6498 100644\n--- a/Documentation/git-send-email.adoc\n+++ b/Documentation/git-send-email.adoc\n@@ -690,10 +690,15 @@ Links of a few such community maintained helpers are:\n \t  (cross platform client that can send emails using the ProtonMail API)\n \n \t- https://github.com/AdityaGarg8/git-credential-email[git-msgraph]\n \t  (cross platform client that can send emails using the Microsoft Graph API)\n \n+CAVEATS\n+-------\n+\n+include::format-patch-caveats.adoc[]\n+\n SEE ALSO\n --------\n linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)\n \n GIT\n\nbase-commit: 3e0db84c88c57e70ac8be8c196dfa92c5d656fbc\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535458","messageId":"xmqqjywo9fpc.fsf@gitster.g","threadId":"64933","inReplyTo":"format-patch_caveats.281@msgid.xyz","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-08T01:39:11Z","receivedAt":"2026-02-08T01:39:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"kristofferhaugsbakk@fastmail.com writes:\n\n> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>\n> git-format-patch(1), git-send-email(1), and git-am(1) deal with\n> formatting commits as patches, sending them (perhaps directly), and\n> applying them, respectively. Naturally they use a few delimiters to mark\n> where the commit message ends. This can lead to surprising behavior when\n> these delimiters are used in the commit message itself.\n>\n> git-format-patch(1) and git-send-email(1) will accept any commit message\n> and not warn or error about these delimiters being used.[1]\n>\n> Moreover, the presence of unindented diffs in the commit message will\n> cause git-am(1) to apply both the diffs from the commit message as well\n> as the patch section.[2]\n>\n> It is unclear whether any commands in this chain will learn to warn\n> about this. One concern could be that users have learned to rely on\n> the three-dash line rule to conveniently add extra-commit message\n> information in the commit message, knowing that git-am(1) will\n> ignore it.[4]\n>\n> All of this is covered already, technically, However, we should spell\n> out the implications.\n>\n> † 1: There is also git-commit(1) to consider. However, making that\n>      command warn or error out over such delimiters would be disruptive\n>      to all Git users who never use email in their workflow.\n> [2]: Recently patch(1) caused this issue for a project, but it was noted\n>      that git-am(1) has the same behavior[3]\n> [3]: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n> [4]: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n>\n> Reported-by: Matthias Beyer <mail@beyermatthias.de>\n> Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n> Reported-by: Matheus Tavares <matheus.tavb@gmail.com>\n> Reported-by: Chris Packham <judge.packham@gmail.com>\n> Helped-by: Jakob Haufe <sur5r@sur5r.net>\n> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> ---\n>\n> Notes (series):\n>     There might be other things to do here. Mention it in gitfaq(5)?\n>     \n>     § Trailers\n>     \n>     • Reported-by: Matthias Beyer <mail@beyermatthias.de>\n>       • From this thread\n>     Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n>       • From https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/T/#u\n>     Reported-by: Matheus Tavares <matheus.bernardino@usp.br>\n>       • From https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/#t\n>     Reported-by: Chris Packham <judge.packham@gmail.com>\n>       • From https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n>     \n>     (These were all linked in https://lore.kernel.org/git/20260206090358.GA2761602@coredump.intra.peff.net/ )\n>     \n>     Helped-by: Jakob Haufe <sur5r@sur5r.net>\n>       • For the part about patch(1): https://lore.kernel.org/git/f6e4cdb4-ff82-4853-aca5-0c152f287286@app.fastmail.com/T/#mc389dbd2ae02a007cbe57cd16ca4790ecc5a84f7\n\nThe space after three-dash line is to give additional information to\nhelp readers, but the above does not qualify as one.\n\n> +Furthermore, the presence of an unindented diff in the commit message\n> +will not only cut the message short but cause that very diff to be\n> +applied, along with the patch in the patch section.\n\nA line that matches \"^diff \" is taken as the end of the log message,\nand everything that follows is passed to the patch application\nmachinery, and the above description is a consequence of that.  If\nyou have more than one such diff, they may be either applied, or\nsome of them may not match the patch target and the whole thing may\nbe rejected.  Neither is a happy outcome.\n\nQueued.  Thanks.\n"},{"id":"535484","messageId":"42e5ce76-7a51-452b-a66a-85ee57b00181@app.fastmail.com","threadId":"64933","inReplyTo":"xmqqjywo9fpc.fsf@gitster.g","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-08T17:18:48Z","receivedAt":"2026-02-08T17:19:16Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Sun, Feb 8, 2026, at 02:39, Junio C Hamano wrote:\n>>[snip]\n>> ---\n>>\n>> Notes (series):\n>>     There might be other things to do here. Mention it in gitfaq(5)?\n>>\n>>     § Trailers\n>>\n>>     • Reported-by: Matthias Beyer <mail@beyermatthias.de>\n>>       • From this thread\n>>     Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n>>       • From https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/T/#u\n>>     Reported-by: Matheus Tavares <matheus.bernardino@usp.br>\n>>       • From https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/#t\n>>     Reported-by: Chris Packham <judge.packham@gmail.com>\n>>       • From https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n>>\n>>     (These were all linked in https://lore.kernel.org/git/20260206090358.GA2761602@coredump.intra.peff.net/ )\n>>\n>>     Helped-by: Jakob Haufe <sur5r@sur5r.net>\n>>       • For the part about patch(1): https://lore.kernel.org/git/f6e4cdb4-ff82-4853-aca5-0c152f287286@app.fastmail.com/T/#mc389dbd2ae02a007cbe57cd16ca4790ecc5a84f7\n>\n> The space after three-dash line is to give additional information to\n> help readers, but the above does not qualify as one.\n\nIt’s not for you. It’s for the people that got CCd to inform them of the\nyears-ago context where they reported this and why they are mentioned by\nname in the email.\n\nI do go overboard with the writing though sometimes.\n\n>[snip]\n"},{"id":"535494","messageId":"xmqqzf5i7otb.fsf@gitster.g","threadId":"64933","inReplyTo":"32614598-48f0-4e3d-ba8c-e8d96b71dbd9@app.fastmail.com","subject":"Re: [PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-09T00:17:36Z","receivedAt":"2026-02-09T00:17:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> writes:\n\n>> A saving grace is that when the user is stopped with this,\n>> pre-commit hook that inspects the contents to be committed\n>> have already run successfully, so rerunning with \"--no-verify\"\n>> is not with too much risk.  But still, I am not sure if this is a\n>> good thing to do overall.\n>\n> Maybe this is not the right tool[1] but perhaps the hook could respect\n> an env. variable to disable this check and hint about it in the error\n> output?\n\nIt is merely a sample script shipped with the rest of Git, so people\ncan choose to install better alternatives.  I think it is fine to\nkeep the sample script simple and understandable.\n\nIt however is still a little worrysome that the behaviour of the\nsample commit-msg hook updated with the third patch may be used\nagainst helpful suggestions people in projects that employ the\ne-mail based workflow may make to their colleages to deliberately\ncommit a three-dash line followed by material not meant for the\ncommit log proper, which is a useful trick if you are making your\ncommits to be sent over e-mail and never to be merged directly to\nyour target branch.\n"},{"id":"535498","messageId":"20260209065703.GA585828@coredump.intra.peff.net","threadId":"64933","inReplyTo":"cover.1770476279.git.phillip.wood@dunelm.org.uk","subject":"Re: [PATCH 0/3] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-09T06:57:03Z","receivedAt":"2026-02-09T06:57:13Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 07, 2026 at 02:57:59PM +0000, Phillip Wood wrote:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> On 06/02/2026 09:03, Jeff King wrote:\n> > I don't think there is a way to unambiguously parse the single-stream\n> > output that format-patch produces. This is a reasonably well-known\n> > gotcha (at least around here). E.g., some earlier discussions:\n> >\n> >    2024:https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n> >    2022:https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n> >    2015:https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n> \n> If we cannot improve \"git am\" perhaps we should update our sample\n> \"commit-msg\" hook to reject messages that will cause problems. Here\n> are some patches to do that.\n\nI'm not entirely opposed to it, but my initial reaction was two bits of\nskepticism:\n\n  1. I imagine that hardly anybody runs commit-msg hooks in the first\n     place, let alone our sample hook. So I doubt this will get the\n     attention of many people.\n\n  2. I'd guess that these days only a small minority of people care\n     about sending patches by email. So for most people, a warning about\n     their commit message containing a diff or \"---\" will be mostly\n     useless, if not outright confusing.\n\nI'd imagine that documentation updates would be more likely to get read\nby users than the sample hook. And a warning in git-commit itself would\nbe even more obvious (but fall even more afoul of (2) above). Adding a\nwarning to format-patch would help with (2), but at that point it may be\ntoo late to change the commit message.\n\n> We could perhaps think about adding a more prominent warning to the\n> \"git am\" and \"git format-patch\" documentation. The docs for \"git am\"\n> mention that it splits the message on a line starting with \"diff -\"\n> but maybe we should spell out what that means for commit messages that\n> include a diff. In principle \"git format-patch\" could also warn or\n> error out if it creates a mail that \"git am\" cannot import verbatim,\n> I don't know how hard that would be in implement.\n\nI think the patch from Matheus linked above added that format-patch\ncheck.\n\n-Peff\n"},{"id":"535499","messageId":"20260209070018.GB585828@coredump.intra.peff.net","threadId":"64933","inReplyTo":"xmqqldh4b5y2.fsf@gitster.g","subject":"Re: [PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-09T07:00:18Z","receivedAt":"2026-02-09T07:00:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 07, 2026 at 01:27:01PM -0800, Junio C Hamano wrote:\n\n> I have no qualms about the topic up to the previous step, but I know\n> one of the things that I sometimes do will be broken with the change\n> in this step, namely, when I know what I want to write below the\n> three-dash lines, I would commit with \"---\" and additional notes\n> below it, so that I do not forget during \"format-patch\".\n>\n> When the commit is turned into a patch email, possibly with some\n> other material like \"--notes=<ref>\" that adds notes there, the\n> resulting message will have two three-dashes lines, but because \"am\"\n> cuts at the first one, and \"apply\" knows that the garbage lines at\n> front, including three-dash lines, do not matter until it sees \"^diff\",\n> this works out perfectly well.\n> \n> Admittedly, I myself do not send out so many patches as I used to,\n> but I suspect that there are others who have discovered this trick\n> independently, and they would be unhappy to be interrupted by\n> commit-msg hook like this.\n\nI do it, too, though not all that often. Once upon a time I had a patch\nto teach git-commit to auto-convert lines after \"---\" into a note (which\nwould then be formatted back out via format-patch). But I found for my\ngit.git workflow that just letting the \"---\" ride along in the commit\nobject was simpler and easier (since I don't care about having pristine\ncommit objects, as their ultimate fate is to be dropped in favor of what\nis applied upstream).\n\n-Peff\n"},{"id":"535514","messageId":"b0c456ce-94f6-4155-8cbd-3dd75a9cc52c@gmail.com","threadId":"64933","inReplyTo":"20260209070018.GB585828@coredump.intra.peff.net","subject":"Re: [PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-09T10:42:49Z","receivedAt":"2026-02-09T10:42:52Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 09/02/2026 07:00, Jeff King wrote:\n> On Sat, Feb 07, 2026 at 01:27:01PM -0800, Junio C Hamano wrote:\n> \n>> I have no qualms about the topic up to the previous step, but I know\n>> one of the things that I sometimes do will be broken with the change\n>> in this step, namely, when I know what I want to write below the\n>> three-dash lines, I would commit with \"---\" and additional notes\n>> below it, so that I do not forget during \"format-patch\".\n>>\n>> When the commit is turned into a patch email, possibly with some\n>> other material like \"--notes=<ref>\" that adds notes there, the\n>> resulting message will have two three-dashes lines, but because \"am\"\n>> cuts at the first one, and \"apply\" knows that the garbage lines at\n>> front, including three-dash lines, do not matter until it sees \"^diff\",\n>> this works out perfectly well.\n>>\n>> Admittedly, I myself do not send out so many patches as I used to,\n>> but I suspect that there are others who have discovered this trick\n>> independently, and they would be unhappy to be interrupted by\n>> commit-msg hook like this.\n> \n> I do it, too, though not all that often. Once upon a time I had a patch\n> to teach git-commit to auto-convert lines after \"---\" into a note (which\n> would then be formatted back out via format-patch). But I found for my\n> git.git workflow that just letting the \"---\" ride along in the commit\n> object was simpler and easier (since I don't care about having pristine\n> commit objects, as their ultimate fate is to be dropped in favor of what\n> is applied upstream).\n\nI do it too occasionally. I had planned just to use \"--no-verify\" when I \ndid that but maybe we should just drop this patch. We could make it \nconfigurable as Kristoffer suggested, or, as we have the raw message, we \ncould look for a special comment like \"# allow ---\" but I'm not sure I \nwant to spend much more time on this. At least \"---\" only truncates the \nmessage rather than applying an unwanted patch.\n\nThanks\n\nPhillip\n\n"},{"id":"535515","messageId":"f5f100de-815e-4bf3-832f-3d473413c635@gmail.com","threadId":"64933","inReplyTo":"20260209065703.GA585828@coredump.intra.peff.net","subject":"Re: [PATCH 0/3] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-09T10:43:23Z","receivedAt":"2026-02-09T10:43:26Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 09/02/2026 06:57, Jeff King wrote:\n> On Sat, Feb 07, 2026 at 02:57:59PM +0000, Phillip Wood wrote:\n> \n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> On 06/02/2026 09:03, Jeff King wrote:\n>>> I don't think there is a way to unambiguously parse the single-stream\n>>> output that format-patch produces. This is a reasonably well-known\n>>> gotcha (at least around here). E.g., some earlier discussions:\n>>>\n>>>     2024:https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n>>>     2022:https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n>>>     2015:https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n>>\n>> If we cannot improve \"git am\" perhaps we should update our sample\n>> \"commit-msg\" hook to reject messages that will cause problems. Here\n>> are some patches to do that.\n> \n> I'm not entirely opposed to it, but my initial reaction was two bits of\n> skepticism:\n> \n>    1. I imagine that hardly anybody runs commit-msg hooks in the first\n>       place, let alone our sample hook. So I doubt this will get the\n>       attention of many people.\n\nI think that's fair, but having it in the sample hook doesn't do any harm.\n\n>    2. I'd guess that these days only a small minority of people care\n>       about sending patches by email. So for most people, a warning about\n>       their commit message containing a diff or \"---\" will be mostly\n>       useless, if not outright confusing.\n\nPeople do download patches from github and apply them even if they're \nnot using a email based workflow. I'm not entirely clear but I think \nthat's what happened in the post Matthias linked to. Though if they're \nusing \"patch\" rather than \"git am\" to apply them indenting the diff wont \nhelp.\n\n> I'd imagine that documentation updates would be more likely to get read\n> by users than the sample hook. And a warning in git-commit itself would\n> be even more obvious (but fall even more afoul of (2) above). Adding a\n> warning to format-patch would help with (2), but at that point it may be\n> too late to change the commit message.\n\nKristoffer has kindly updated the documentation. I'm wary of adding a \nwarning to \"git commit\" for the reason you gave above. We could make it \nopt-in but then hardly anyone would probably set that config option.\n\nThanks\n\nPhillip\n\n>> We could perhaps think about adding a more prominent warning to the\n>> \"git am\" and \"git format-patch\" documentation. The docs for \"git am\"\n>> mention that it splits the message on a line starting with \"diff -\"\n>> but maybe we should spell out what that means for commit messages that\n>> include a diff. In principle \"git format-patch\" could also warn or\n>> error out if it creates a mail that \"git am\" cannot import verbatim,\n>> I don't know how hard that would be in implement.\n> \n> I think the patch from Matheus linked above added that format-patch\n> check.\n> \n> -Peff\n> \n\n"},{"id":"535516","messageId":"gfxpnecn2cdtmeiape2d4x5aybuyyqi4c7m6te3khgct34dd44@wqusigna2nsp","threadId":"64933","inReplyTo":"f5f100de-815e-4bf3-832f-3d473413c635@gmail.com","subject":"Re: [PATCH 0/3] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Matthias Beyer","fromEmail":"mail@beyermatthias.de","sentAt":"2026-02-09T11:07:40Z","receivedAt":"2026-02-09T11:07:49Z","isPatch":true,"sender":{"key":"mail@beyermatthias.de","avatar":null},"body":"On Mon, Feb 09, 2026 at 10:43:23AM +0000, Phillip Wood wrote:\n> >    2. I'd guess that these days only a small minority of people care\n> >       about sending patches by email. So for most people, a warning about\n> >       their commit message containing a diff or \"---\" will be mostly\n> >       useless, if not outright confusing.\n> \n> People do download patches from github and apply them even if they're not\n> using a email based workflow. I'm not entirely clear but I think that's what\n> happened in the post Matthias linked to. Though if they're using \"patch\"\n> rather than \"git am\" to apply them indenting the diff wont help.\n\nYes, the original post was exactly that issue.\n\nI can add that distributions also do that quite often when they apply\nfixes from upstream that have not made it into a package release yet. At\nleast for the NixOS distribution, we do that quite a lot (a totally\nunscientific grep through nixpkgs gave ~2800 instances where we fetch\npatches).\n\nOf course it is the obligation of the distribution to check the patches\nthat are applied to packages. But in this case they of course use\n`patch` rather than `git am`. Still, that the diff from a commit message\nwill be applied as well is something even advanced users do not know\n(I myself am using git for over 15 years, and I am comfortable with\nemail patch based workflows - though, I didn't know about that fact and\nwould have definitively fallen into that \"trap\").\n\n> Kristoffer has kindly updated the documentation. I'm wary of adding a\n> warning to \"git commit\" for the reason you gave above. We could make it\n> opt-in but then hardly anyone would probably set that config option.\n\nI agree on that part.\n\nMatthias\n"},{"id":"535555","messageId":"aYoEO0CcVt2Qjgnb@pks.im","threadId":"64933","inReplyTo":"20260206090358.GA2761602@coredump.intra.peff.net","subject":"Re: git-am applies commit message diffs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-02-09T15:58:51Z","receivedAt":"2026-02-09T15:59:03Z","isPatch":false,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Feb 06, 2026 at 04:03:58AM -0500, Jeff King wrote:\n> On Fri, Feb 06, 2026 at 09:18:50AM +0100, Matthias Beyer wrote:\n> \n> > That said, I am no expert in either C or the git codebase at all, but\n> > from what I saw from reading the git-am codebase, it looks like it tries\n> > to find the patch by looking for three dashes on a line with a linebreak\n> > behind (\"---\\n\").\n> \n> Yes, that is how the split is made.\n> \n> > From what I read, it looks for that from the first line.\n> > What I would think of here is looking for that \"patchbreak\" from the\n> > _end_ of the email rather than from the top, that would have prevented\n> > this issue, right?\n> \n> The patch itself may legitimately contain \"---\" on a line by itself (it\n> would indicate that the line \"--\" was removed from a file). That would\n> confuse your parser, including in a way that we end up only applying\n> part of the diff (everything before that fake \"---\" becomes commit\n> message, and everything after becomes cover-letter material up to the\n> next \"diff\" line).\n> \n> I suspect it also creates corner cases with cover-letter material\n> (between the \"---\" and the diff itself) that itself contains any \"---\"\n> marker.\n> \n> I don't think there is a way to unambiguously parse the single-stream\n> output that format-patch produces. This is a reasonably well-known\n> gotcha (at least around here). E.g., some earlier discussions:\n> \n>   2024: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n>   2022: https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n>   2015: https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n> \n> There are probably more, but it's actually a tricky thing to search for\n> in the archive, so I stopped digging. ;)\n\nMaybe we can't parse it unambiguously. But what we _can_ detect is that\na patch is ambiguous in the first place, right? So maybe we could extend\ngit-am(1) to bail by default with a hint that tells the user that:\n\n  - They ought to double-check the patch.\n\n  - They can override the check with \"--accept-ambiguous-patch\".\n\nIt at least notifies the user that something potentially-fishy is going\non, even though it still shifts the burden onto the person that applies\nthe patch. But I guess that cannot ever be avoided anyway, at least in\nthe general case.\n\nPatrick\n"},{"id":"535563","messageId":"bf5d1e84-2a59-4e1b-a524-c8b251dbae70@gmail.com","threadId":"64933","inReplyTo":"format-patch_caveats.281@msgid.xyz","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-09T16:42:41Z","receivedAt":"2026-02-09T16:42:45Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Kristoffer\n\nThanks for working on this. I've left a few comments below but I think \nwhat you have here is pretty good already.\n\nOn 08/02/2026 00:11, kristofferhaugsbakk@fastmail.com wrote:\n> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> \n> git-format-patch(1), git-send-email(1), and git-am(1) deal with\n\nI found the mention of git-send-email here and in the documentation a \nbit distracting as it doesn't do any formatting itself - it just runs \n\"git format-patch\"\n\n> † 1: There is also git-commit(1) to consider. However, making that\n>       command warn or error out over such delimiters would be disruptive\n>       to all Git users who never use email in their workflow.\n\nThis reference is formatted differently to the rest.\n\n> [2]: Recently patch(1) caused this issue for a project, but it was noted\n>       that git-am(1) has the same behavior[3]\n> [3]: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n> [4]: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n\n> diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n> new file mode 100644\n> index 00000000000..2accf2763fd\n> --- /dev/null\n> +++ b/Documentation/format-patch-caveats.adoc\n> @@ -0,0 +1,39 @@\n> +Patches produced by linkgit:git-format-patch[1] or\n> +linkgit:git-send-email[1] are inline. This means that the output of\n> +these two commands can lead to a different commit message when applied\n> +with linkgit:git-am[1]. It can also mean that the patch is not applied\n> +correctly.\n\nIs this last sentence referring to diffs in the commit message being \napplied? I don't think there are circumstances where the patch itself is \nnot applied correctly.\n\n> +The commit message might contain a three-dash line (`---`) which was\n> +perhaps meant to be a thematic break. That means that the commit message\n> +will be cut short. The presence of a line starting with \"Index: \" can\n> +cause the patch not to be found, giving an error about an empty patch.\n> +\n> +Furthermore, the presence of an unindented diff in the commit message\n> +will not only cut the message short but cause that very diff to be\n> +applied, along with the patch in the patch section. The commit message\n> +might for example have a diff in a GitHub MarkDown code fence:\n> +\n> +----\n> +```\n> +diff ...\n> +```\n> +----\n\nI'm not sure the markdown really adds anything here\n\n> +The solution for this is to indent the diff instead:\n> +\n> +----\n> +    diff ...\n> +----\n> +\n> +This loss of fidelity might be simple to notice if you are applying\n> +patches directly from a mailbox. However, a commit authored long ago\n> +might be applied in a different context, perhaps because many changes\n> +are being integrated via patch files and the\n> +linkgit:git-format-patch[1] format is trusted to import changes of a\n> +Git origin.\n\nThis last sentence lost me a bit. Is this talking about commits that \nhave been pushed to a forge and then some downloads it as a patch? It \nwould certainly be helpful to explain that even if you're not using an \nemail based workflow, it is possible to be caught out by these issues.\n\n> +One might want to use a general-purpose utility like patch(1) instead,\n\n\"Given these limitations, one might be tempted to ...\"?\n\n> +given these limitations. However, patch(1) will not only look for\n> +unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n> +diffs as well.\n\nThis is useful context.\n\nThanks\n\nPhillip\n\n> diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\n> index 0c94776e296..18f5b950825 100644\n> --- a/Documentation/git-am.adoc\n> +++ b/Documentation/git-am.adoc\n> @@ -259,10 +259,13 @@ message.  Any line that is of the form:\n>   * a line that begins with \"Index: \"\n>   \n>   is taken as the beginning of a patch, and the commit log message\n>   is terminated before the first occurrence of such a line.\n>   \n> +This means that the content of the commit message can inadverently\n> +interrupt the processing (see the <<caveats,CAVEATS>> section below).\n> +\n>   When initially invoking `git am`, you give it the names of the mailboxes\n>   to process.  Upon seeing the first patch that does not apply, it\n>   aborts in the middle.  You can recover from this in one of two ways:\n>   \n>   . skip the current patch by re-running the command with the `--skip`\n> @@ -281,10 +284,16 @@ Before any patches are applied, ORIG_HEAD is set to the tip of the\n>   current branch.  This is useful if you have problems with multiple\n>   commits, like running 'git am' on the wrong branch or an error in the\n>   commits that is more easily fixed by changing the mailbox (e.g.\n>   errors in the \"From:\" lines).\n>   \n> +[[caveats]]\n> +CAVEATS\n> +-------\n> +\n> +include::format-patch-caveats.adoc[]\n> +\n>   HOOKS\n>   -----\n>   This command can run `applypatch-msg`, `pre-applypatch`,\n>   and `post-applypatch` hooks.  See linkgit:githooks[5] for more\n>   information.\n> diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\n> index 9a7807ca71a..36851aaf5e1 100644\n> --- a/Documentation/git-format-patch.adoc\n> +++ b/Documentation/git-format-patch.adoc\n> @@ -796,10 +796,14 @@ CAVEATS\n>   Note that `format-patch` will omit merge commits from the output, even\n>   if they are part of the requested range. A simple \"patch\" does not\n>   include enough information for the receiving end to reproduce the same\n>   merge commit.\n>   \n> +'''\n> +\n> +include::format-patch-caveats.adoc[]\n> +\n>   SEE ALSO\n>   --------\n>   linkgit:git-am[1], linkgit:git-send-email[1]\n>   \n>   GIT\n> diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc\n> index ebe8853e9f5..0b118df6498 100644\n> --- a/Documentation/git-send-email.adoc\n> +++ b/Documentation/git-send-email.adoc\n> @@ -690,10 +690,15 @@ Links of a few such community maintained helpers are:\n>   \t  (cross platform client that can send emails using the ProtonMail API)\n>   \n>   \t- https://github.com/AdityaGarg8/git-credential-email[git-msgraph]\n>   \t  (cross platform client that can send emails using the Microsoft Graph API)\n>   \n> +CAVEATS\n> +-------\n> +\n> +include::format-patch-caveats.adoc[]\n> +\n>   SEE ALSO\n>   --------\n>   linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)\n>   \n>   GIT\n> \n> base-commit: 3e0db84c88c57e70ac8be8c196dfa92c5d656fbc\n\n"},{"id":"535582","messageId":"c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com","threadId":"64933","inReplyTo":"bf5d1e84-2a59-4e1b-a524-c8b251dbae70@gmail.com","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-09T17:59:12Z","receivedAt":"2026-02-09T18:00:02Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"Hi Phillip\n\nOn Mon, Feb 9, 2026, at 17:42, Phillip Wood wrote:\n>[snip]\n> On 08/02/2026 00:11, kristofferhaugsbakk@fastmail.com wrote:\n>> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>>\n>> git-format-patch(1), git-send-email(1), and git-am(1) deal with\n>\n> I found the mention of git-send-email here and in the documentation a\n> bit distracting as it doesn't do any formatting itself - it just runs\n> \"git format-patch\"\n\nOkay, I see now that git-send-email(1) already says that it uses\ngit-format-patch(1). So we can scratch that command mention. The user\ncan see from the rest of the git-send-email(1) doc why we have a caveat\nabout git-format-patch(1).\n\nI first thought that it wouldn’t be obvious why we are talking\nabout git-format-patch(1) here.\n\n>\n>> † 1: There is also git-commit(1) to consider. However, making that\n>>       command warn or error out over such delimiters would be disruptive\n>>       to all Git users who never use email in their workflow.\n>\n> This reference is formatted differently to the rest.\n\nOkay, thanks.\n\nI will change to using just one style in the next round. :)\n\n( https://lore.kernel.org/git/doc_am_gitlinks_and_am.messageId.321@msgid.xyz/T/#m38026ad670e866b9ef1a0ef3827fd69316bb1aa3 )\n\n>>[snip]\n>> +Patches produced by linkgit:git-format-patch[1] or\n>> +linkgit:git-send-email[1] are inline. This means that the output of\n>> +these two commands can lead to a different commit message when applied\n>> +with linkgit:git-am[1]. It can also mean that the patch is not applied\n>> +correctly.\n>\n> Is this last sentence referring to diffs in the commit message being\n> applied? I don't think there are circumstances where the patch itself is\n> not applied correctly.\n\nI tested with a line like\n\n    Index x\n\nYesterday and got an empty patch when running git-am(1). But I couldn’t\nreproduce now. I must have made a mistake.\n\nI think this should be changed to:\n\n    It can also mean that the patch that is applied is not the same as\n    the one that was generated.\n\n(generated = shorthand for made by git-format-patch(1))\n\nThis sentence would then serve as an introduction for the “Furthermore,”\nparagraph later.\n\n>>[snip]\n>> +----\n>> +```\n>> +diff ...\n>> +```\n>> +----\n>\n> I'm not sure the markdown really adds anything here\n\nI don’t understand? It demonstrates a markup for code which does not use\nindentation.\n\nWell, maybe it should be:\n\n    ----\n    ```\n    diff ...\n    ...\n    ```\n    ----\n\nOr maybe...\n\n    ----\n    ```\n    diff --git a/example.txt b/example.txt\n    ...\n    ```\n    ----\n\nI’m leaning towards the latter.\n\n>>[snip]\n>> +One might want to use a general-purpose utility like patch(1) instead,\n>\n> \"Given these limitations, one might be tempted to ...\"?\n\nThat’s good. That leads with the problem instead letting it trail off at\nthe end of the sentence. I’ll use that.\n\n>> +given these limitations. However, patch(1) will not only look for\n>> +unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n>> +diffs as well.\n>\n> This is useful context.\n>\n> Thanks\n>\n> Phillip\n\nThanks for taking a look. It’s always appreciated.\n"},{"id":"535614","messageId":"V2_format-patch_caveats.34b@msgid.xyz","threadId":"64933","inReplyTo":"format-patch_caveats.281@msgid.xyz","subject":"[PATCH v2] doc: add caveat about roundtripping format-patch","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-09T22:37:05Z","receivedAt":"2026-02-09T22:37:22Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\ngit-format-patch(1) and git-am(1) deal with formatting commits as\npatches and applying them, respectively. Naturally they use a few\ndelimiters to mark where the commit message ends. This can lead to\nsurprising behavior when these delimiters are used in the commit\nmessage itself.\n\ngit-format-patch(1) will accept any commit message and not warn or error\nabout these delimiters being used.[1]\n\nEspecially problematic is the presence of unindented diffs in the commit\nmessage; the patch machinery will naturally (since the commit message\nhas ended) try to apply that diff and everything after it.[2]\n\nIt is unclear whether any commands in this chain will learn to warn\nabout this. One concern could be that users have learned to rely on\nthe three-dash line rule to conveniently add extra-commit message\ninformation in the commit message, knowing that git-am(1) will\nignore it.[4]\n\nAll of this is covered already, technically. However, we should spell\nout the implications.\n\n† 1: There is also git-commit(1) to consider. However, making that\n     command warn or error out over such delimiters would be disruptive\n     to all Git users who never use email in their workflow.\n† 2: Recently patch(1) caused this issue for a project, but it was noted\n     that git-am(1) has the same behavior[3]\n† 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n† 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n     https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\n\nReported-by: Matthias Beyer <mail@beyermatthias.de>\nReported-by: Christoph Anton Mitterer <calestyo@scientia.org>\nReported-by: Matheus Tavares <matheus.tavb@gmail.com>\nReported-by: Chris Packham <judge.packham@gmail.com>\nHelped-by: Jakob Haufe <sur5r@sur5r.net>\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\n---\n\nv2:\n\nAddress feedback from Phillip Wood.\n\nCc: Phillip Wood <phillip.wood@dunelm.org.uk>\n\n• Drop the code blocks with the diffs; the prose speaks for itself, no need\n  to take up space\n• Don’t discuss git-send-email(1). We already know that git-format-patch(1)\n  is the generator. It is mentioned in git-send-email(1).\n• Try to be more clear about the case where someone might be applying a\n  diff. Use the example from Matthias Beyer in:\n\n      https://lore.kernel.org/git/gfxpnecn2cdtmeiape2d4x5aybuyyqi4c7m6te3khgct34dd44@wqusigna2nsp/\n\n  Hopefully I explained it correctly?\n• Add a “this goes to show...”... which seems to emphasize the point\n  without being redundant. Hopefully.\n\nTry to address feedback from Junio C Hamano by adding more nuance: the diff\nin the commit message might be applied as well, or the patch machinery\nmight trip on something and fail.\n\nFinally, in the middle of discussing the three possible cmt. message\ndelimiters, I noticed that the three points were drifting apart. So I\ndecided to use the list already used in git-am(1) and be done with it in\none place.\n\n---\n\nIt seems that the section break in git-format-patch(1) does not get\napplied in the man output (according to `Documentation/doc-diff`\napparently)? Maybe this is the wrong construct? I couldn’t find any\nother thematic breaks here (though there are several variations).\n---\n Documentation/format-patch-caveats.adoc       | 36 +++++++++++++++++++\n .../format-patch-end-of-commit-message.adoc   |  3 ++\n Documentation/git-am.adoc                     | 15 ++++++--\n Documentation/git-format-patch.adoc           |  4 +++\n Documentation/git-send-email.adoc             |  5 +++\n 5 files changed, 60 insertions(+), 3 deletions(-)\n create mode 100644 Documentation/format-patch-caveats.adoc\n create mode 100644 Documentation/format-patch-end-of-commit-message.adoc\n\ndiff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\nnew file mode 100644\nindex 00000000000..c666d709742\n--- /dev/null\n+++ b/Documentation/format-patch-caveats.adoc\n@@ -0,0 +1,36 @@\n+Patches produced by linkgit:git-format-patch[1] are inline. This means\n+that the output from that command can lead to a different commit message\n+when applied with linkgit:git-am[1]. It can also mean that the patch\n+that is applied is not the same as the one that was generated, or that\n+the patch application fails outright.\n+ifdef::git-am[]\n+See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n+endif::git-am[]\n+\n+ifndef::git-am[]\n+Any line that is of the form:\n+\n+include::format-patch-end-of-commit-message.adoc[]\n+\n+will terminate the commit message and cause the patch machinery to start\n+searching for patches to apply.\n+endif::git-am[]\n+\n+Note that this is especially problematic for unindented diffs that occur\n+in the commit message; the diff in the commit message might get applied\n+along with the patch section, or the patch application machinery might\n+trip up because the patch target doesn't apply. This could for example\n+be caused by a diff in a GitHub Markdown code block.\n+\n+This loss of fidelity might be simple to notice if you are applying\n+patches directly from a mailbox. However, changes originating from Git\n+could be applied in bulk, in which case this would be much harder to\n+notice. This could for example be a Linux distribution which uses patch\n+files to apply changes on top of the commits from the upstream\n+repositories. This goes to show that this behavior does not only impact\n+email workflows.\n+\n+Given these limitations, one might be tempted to use a general-purpose\n+utility like patch(1) instead. However, patch(1) will not only look for\n+unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n+diffs as well.\ndiff --git a/Documentation/format-patch-end-of-commit-message.adoc b/Documentation/format-patch-end-of-commit-message.adoc\nnew file mode 100644\nindex 00000000000..47399ae7266\n--- /dev/null\n+++ b/Documentation/format-patch-end-of-commit-message.adoc\n@@ -0,0 +1,3 @@\n+* three-dashes and end-of-line, or\n+* a line that begins with \"diff -\", or\n+* a line that begins with \"Index: \"\ndiff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\nindex 0c94776e296..756dfd722b9 100644\n--- a/Documentation/git-am.adoc\n+++ b/Documentation/git-am.adoc\n@@ -231,10 +231,11 @@ applying.\n --allow-empty::\n \tAfter a patch failure on an input e-mail message lacking a patch,\n \tcreate an empty commit with the contents of the e-mail message\n \tas its log message.\n \n+[[discussion]]\n DISCUSSION\n ----------\n \n The commit author name is taken from the \"From: \" line of the\n message, and commit author date is taken from the \"Date: \" line\n@@ -252,17 +253,18 @@ where the patch begins.  Excess whitespace at the end of each\n line is automatically stripped.\n \n The patch is expected to be inline, directly following the\n message.  Any line that is of the form:\n \n-* three-dashes and end-of-line, or\n-* a line that begins with \"diff -\", or\n-* a line that begins with \"Index: \"\n+include::format-patch-end-of-commit-message.adoc[]\n \n is taken as the beginning of a patch, and the commit log message\n is terminated before the first occurrence of such a line.\n \n+This means that the contents of the commit message can inadvertently\n+interrupt the processing (see the <<caveats,CAVEATS>> section below).\n+\n When initially invoking `git am`, you give it the names of the mailboxes\n to process.  Upon seeing the first patch that does not apply, it\n aborts in the middle.  You can recover from this in one of two ways:\n \n . skip the current patch by re-running the command with the `--skip`\n@@ -281,10 +283,17 @@ Before any patches are applied, ORIG_HEAD is set to the tip of the\n current branch.  This is useful if you have problems with multiple\n commits, like running 'git am' on the wrong branch or an error in the\n commits that is more easily fixed by changing the mailbox (e.g.\n errors in the \"From:\" lines).\n \n+[[caveats]]\n+CAVEATS\n+-------\n+\n+:git-am: 1\n+include::format-patch-caveats.adoc[]\n+\n HOOKS\n -----\n This command can run `applypatch-msg`, `pre-applypatch`,\n and `post-applypatch` hooks.  See linkgit:githooks[5] for more\n information.\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 9a7807ca71a..36851aaf5e1 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -796,10 +796,14 @@ CAVEATS\n Note that `format-patch` will omit merge commits from the output, even\n if they are part of the requested range. A simple \"patch\" does not\n include enough information for the receiving end to reproduce the same\n merge commit.\n \n+'''\n+\n+include::format-patch-caveats.adoc[]\n+\n SEE ALSO\n --------\n linkgit:git-am[1], linkgit:git-send-email[1]\n \n GIT\ndiff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc\nindex ebe8853e9f5..0b118df6498 100644\n--- a/Documentation/git-send-email.adoc\n+++ b/Documentation/git-send-email.adoc\n@@ -690,10 +690,15 @@ Links of a few such community maintained helpers are:\n \t  (cross platform client that can send emails using the ProtonMail API)\n \n \t- https://github.com/AdityaGarg8/git-credential-email[git-msgraph]\n \t  (cross platform client that can send emails using the Microsoft Graph API)\n \n+CAVEATS\n+-------\n+\n+include::format-patch-caveats.adoc[]\n+\n SEE ALSO\n --------\n linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)\n \n GIT\n\nInterdiff against v1:\n  diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n  index 2accf2763fd..c666d709742 100644\n  --- a/Documentation/format-patch-caveats.adoc\n  +++ b/Documentation/format-patch-caveats.adoc\n  @@ -1,39 +1,36 @@\n  -Patches produced by linkgit:git-format-patch[1] or\n  -linkgit:git-send-email[1] are inline. This means that the output of\n  -these two commands can lead to a different commit message when applied\n  -with linkgit:git-am[1]. It can also mean that the patch is not applied\n  -correctly.\n  +Patches produced by linkgit:git-format-patch[1] are inline. This means\n  +that the output from that command can lead to a different commit message\n  +when applied with linkgit:git-am[1]. It can also mean that the patch\n  +that is applied is not the same as the one that was generated, or that\n  +the patch application fails outright.\n  +ifdef::git-am[]\n  +See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n  +endif::git-am[]\n   \n  -The commit message might contain a three-dash line (`---`) which was\n  -perhaps meant to be a thematic break. That means that the commit message\n  -will be cut short. The presence of a line starting with \"Index: \" can\n  -cause the patch not to be found, giving an error about an empty patch.\n  +ifndef::git-am[]\n  +Any line that is of the form:\n   \n  -Furthermore, the presence of an unindented diff in the commit message\n  -will not only cut the message short but cause that very diff to be\n  -applied, along with the patch in the patch section. The commit message\n  -might for example have a diff in a GitHub MarkDown code fence:\n  +include::format-patch-end-of-commit-message.adoc[]\n   \n  -----\n  -```\n  -diff ...\n  -```\n  -----\n  +will terminate the commit message and cause the patch machinery to start\n  +searching for patches to apply.\n  +endif::git-am[]\n   \n  -The solution for this is to indent the diff instead:\n  -\n  -----\n  -    diff ...\n  -----\n  +Note that this is especially problematic for unindented diffs that occur\n  +in the commit message; the diff in the commit message might get applied\n  +along with the patch section, or the patch application machinery might\n  +trip up because the patch target doesn't apply. This could for example\n  +be caused by a diff in a GitHub Markdown code block.\n   \n   This loss of fidelity might be simple to notice if you are applying\n  -patches directly from a mailbox. However, a commit authored long ago\n  -might be applied in a different context, perhaps because many changes\n  -are being integrated via patch files and the\n  -linkgit:git-format-patch[1] format is trusted to import changes of a\n  -Git origin.\n  +patches directly from a mailbox. However, changes originating from Git\n  +could be applied in bulk, in which case this would be much harder to\n  +notice. This could for example be a Linux distribution which uses patch\n  +files to apply changes on top of the commits from the upstream\n  +repositories. This goes to show that this behavior does not only impact\n  +email workflows.\n   \n  -One might want to use a general-purpose utility like patch(1) instead,\n  -given these limitations. However, patch(1) will not only look for\n  +Given these limitations, one might be tempted to use a general-purpose\n  +utility like patch(1) instead. However, patch(1) will not only look for\n   unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n   diffs as well.\n  diff --git a/Documentation/format-patch-end-of-commit-message.adoc b/Documentation/format-patch-end-of-commit-message.adoc\n  new file mode 100644\n  index 00000000000..47399ae7266\n  --- /dev/null\n  +++ b/Documentation/format-patch-end-of-commit-message.adoc\n  @@ -0,0 +1,3 @@\n  +* three-dashes and end-of-line, or\n  +* a line that begins with \"diff -\", or\n  +* a line that begins with \"Index: \"\n  diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\n  index 18f5b950825..756dfd722b9 100644\n  --- a/Documentation/git-am.adoc\n  +++ b/Documentation/git-am.adoc\n  @@ -231,10 +231,11 @@ applying.\n   --allow-empty::\n   \tAfter a patch failure on an input e-mail message lacking a patch,\n   \tcreate an empty commit with the contents of the e-mail message\n   \tas its log message.\n   \n  +[[discussion]]\n   DISCUSSION\n   ----------\n   \n   The commit author name is taken from the \"From: \" line of the\n   message, and commit author date is taken from the \"Date: \" line\n  @@ -252,18 +253,16 @@ where the patch begins.  Excess whitespace at the end of each\n   line is automatically stripped.\n   \n   The patch is expected to be inline, directly following the\n   message.  Any line that is of the form:\n   \n  -* three-dashes and end-of-line, or\n  -* a line that begins with \"diff -\", or\n  -* a line that begins with \"Index: \"\n  +include::format-patch-end-of-commit-message.adoc[]\n   \n   is taken as the beginning of a patch, and the commit log message\n   is terminated before the first occurrence of such a line.\n   \n  -This means that the content of the commit message can inadverently\n  +This means that the contents of the commit message can inadvertently\n   interrupt the processing (see the <<caveats,CAVEATS>> section below).\n   \n   When initially invoking `git am`, you give it the names of the mailboxes\n   to process.  Upon seeing the first patch that does not apply, it\n   aborts in the middle.  You can recover from this in one of two ways:\n  @@ -288,10 +287,11 @@ errors in the \"From:\" lines).\n   \n   [[caveats]]\n   CAVEATS\n   -------\n   \n  +:git-am: 1\n   include::format-patch-caveats.adoc[]\n   \n   HOOKS\n   -----\n   This command can run `applypatch-msg`, `pre-applypatch`,\n\nRange-diff against v1:\n1:  4bed8f55b98 ! 1:  c54f394bb33 doc: add caveat about roundtripping format-patch\n    @@ Metadata\n      ## Commit message ##\n         doc: add caveat about roundtripping format-patch\n     \n    -    git-format-patch(1), git-send-email(1), and git-am(1) deal with\n    -    formatting commits as patches, sending them (perhaps directly), and\n    -    applying them, respectively. Naturally they use a few delimiters to mark\n    -    where the commit message ends. This can lead to surprising behavior when\n    -    these delimiters are used in the commit message itself.\n    +    git-format-patch(1) and git-am(1) deal with formatting commits as\n    +    patches and applying them, respectively. Naturally they use a few\n    +    delimiters to mark where the commit message ends. This can lead to\n    +    surprising behavior when these delimiters are used in the commit\n    +    message itself.\n     \n    -    git-format-patch(1) and git-send-email(1) will accept any commit message\n    -    and not warn or error about these delimiters being used.[1]\n    +    git-format-patch(1) will accept any commit message and not warn or error\n    +    about these delimiters being used.[1]\n     \n    -    Moreover, the presence of unindented diffs in the commit message will\n    -    cause git-am(1) to apply both the diffs from the commit message as well\n    -    as the patch section.[2]\n    +    Especially problematic is the presence of unindented diffs in the commit\n    +    message; the patch machinery will naturally (since the commit message\n    +    has ended) try to apply that diff and everything after it.[2]\n     \n         It is unclear whether any commands in this chain will learn to warn\n         about this. One concern could be that users have learned to rely on\n    @@ Commit message\n         information in the commit message, knowing that git-am(1) will\n         ignore it.[4]\n     \n    -    All of this is covered already, technically, However, we should spell\n    +    All of this is covered already, technically. However, we should spell\n         out the implications.\n     \n         † 1: There is also git-commit(1) to consider. However, making that\n              command warn or error out over such delimiters would be disruptive\n              to all Git users who never use email in their workflow.\n    -    [2]: Recently patch(1) caused this issue for a project, but it was noted\n    +    † 2: Recently patch(1) caused this issue for a project, but it was noted\n              that git-am(1) has the same behavior[3]\n    -    [3]: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n    -    [4]: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n    +    † 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n    +    † 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n    +         https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\n     \n         Reported-by: Matthias Beyer <mail@beyermatthias.de>\n         Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n    @@ Commit message\n         Helped-by: Jakob Haufe <sur5r@sur5r.net>\n         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n     \n    +    ---\n    +\n    +    v2:\n    +\n    +    Address feedback from Phillip Wood.\n    +\n    +    Cc: Phillip Wood <phillip.wood@dunelm.org.uk>\n    +\n    +    • Drop the code blocks with the diffs; the prose speaks for itself, no need\n    +      to take up space\n    +    • Don’t discuss git-send-email(1). We already know that git-format-patch(1)\n    +      is the generator. It is mentioned in git-send-email(1).\n    +    • Try to be more clear about the case where someone might be applying a\n    +      diff. Use the example from Matthias Beyer in:\n    +\n    +          https://lore.kernel.org/git/gfxpnecn2cdtmeiape2d4x5aybuyyqi4c7m6te3khgct34dd44@wqusigna2nsp/\n    +\n    +      Hopefully I explained it correctly?\n    +    • Add a “this goes to show...”... which seems to emphasize the point\n    +      without being redundant. Hopefully.\n    +\n    +    Try to address feedback from Junio C Hamano by adding more nuance: the diff\n    +    in the commit message might be applied as well, or the patch machinery\n    +    might trip on something and fail.\n    +\n    +    Finally, in the middle of discussing the three possible cmt. message\n    +    delimiters, I noticed that the three points were drifting apart. So I\n    +    decided to use the list already used in git-am(1) and be done with it in\n    +    one place.\n    +\n    +    ---\n    +\n    +    It seems that the section break in git-format-patch(1) does not get\n    +    applied in the man output (according to `Documentation/doc-diff`\n    +    apparently)? Maybe this is the wrong construct? I couldn’t find any\n    +    other thematic breaks here (though there are several variations).\n    +\n      ## Documentation/format-patch-caveats.adoc (new) ##\n     @@\n    -+Patches produced by linkgit:git-format-patch[1] or\n    -+linkgit:git-send-email[1] are inline. This means that the output of\n    -+these two commands can lead to a different commit message when applied\n    -+with linkgit:git-am[1]. It can also mean that the patch is not applied\n    -+correctly.\n    -+\n    -+The commit message might contain a three-dash line (`---`) which was\n    -+perhaps meant to be a thematic break. That means that the commit message\n    -+will be cut short. The presence of a line starting with \"Index: \" can\n    -+cause the patch not to be found, giving an error about an empty patch.\n    ++Patches produced by linkgit:git-format-patch[1] are inline. This means\n    ++that the output from that command can lead to a different commit message\n    ++when applied with linkgit:git-am[1]. It can also mean that the patch\n    ++that is applied is not the same as the one that was generated, or that\n    ++the patch application fails outright.\n    ++ifdef::git-am[]\n    ++See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n    ++endif::git-am[]\n     +\n    -+Furthermore, the presence of an unindented diff in the commit message\n    -+will not only cut the message short but cause that very diff to be\n    -+applied, along with the patch in the patch section. The commit message\n    -+might for example have a diff in a GitHub MarkDown code fence:\n    ++ifndef::git-am[]\n    ++Any line that is of the form:\n     +\n    -+----\n    -+```\n    -+diff ...\n    -+```\n    -+----\n    ++include::format-patch-end-of-commit-message.adoc[]\n     +\n    -+The solution for this is to indent the diff instead:\n    ++will terminate the commit message and cause the patch machinery to start\n    ++searching for patches to apply.\n    ++endif::git-am[]\n     +\n    -+----\n    -+    diff ...\n    -+----\n    ++Note that this is especially problematic for unindented diffs that occur\n    ++in the commit message; the diff in the commit message might get applied\n    ++along with the patch section, or the patch application machinery might\n    ++trip up because the patch target doesn't apply. This could for example\n    ++be caused by a diff in a GitHub Markdown code block.\n     +\n     +This loss of fidelity might be simple to notice if you are applying\n    -+patches directly from a mailbox. However, a commit authored long ago\n    -+might be applied in a different context, perhaps because many changes\n    -+are being integrated via patch files and the\n    -+linkgit:git-format-patch[1] format is trusted to import changes of a\n    -+Git origin.\n    ++patches directly from a mailbox. However, changes originating from Git\n    ++could be applied in bulk, in which case this would be much harder to\n    ++notice. This could for example be a Linux distribution which uses patch\n    ++files to apply changes on top of the commits from the upstream\n    ++repositories. This goes to show that this behavior does not only impact\n    ++email workflows.\n     +\n    -+One might want to use a general-purpose utility like patch(1) instead,\n    -+given these limitations. However, patch(1) will not only look for\n    ++Given these limitations, one might be tempted to use a general-purpose\n    ++utility like patch(1) instead. However, patch(1) will not only look for\n     +unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n     +diffs as well.\n     \n    + ## Documentation/format-patch-end-of-commit-message.adoc (new) ##\n    +@@\n    ++* three-dashes and end-of-line, or\n    ++* a line that begins with \"diff -\", or\n    ++* a line that begins with \"Index: \"\n    +\n      ## Documentation/git-am.adoc ##\n    -@@ Documentation/git-am.adoc: message.  Any line that is of the form:\n    +@@ Documentation/git-am.adoc: applying.\n    + \tcreate an empty commit with the contents of the e-mail message\n    + \tas its log message.\n    + \n    ++[[discussion]]\n    + DISCUSSION\n    + ----------\n    + \n    +@@ Documentation/git-am.adoc: line is automatically stripped.\n    + The patch is expected to be inline, directly following the\n    + message.  Any line that is of the form:\n    + \n    +-* three-dashes and end-of-line, or\n    +-* a line that begins with \"diff -\", or\n    +-* a line that begins with \"Index: \"\n    ++include::format-patch-end-of-commit-message.adoc[]\n    + \n      is taken as the beginning of a patch, and the commit log message\n      is terminated before the first occurrence of such a line.\n      \n    -+This means that the content of the commit message can inadverently\n    ++This means that the contents of the commit message can inadvertently\n     +interrupt the processing (see the <<caveats,CAVEATS>> section below).\n     +\n      When initially invoking `git am`, you give it the names of the mailboxes\n    @@ Documentation/git-am.adoc: commits, like running 'git am' on the wrong branch or\n     +CAVEATS\n     +-------\n     +\n    ++:git-am: 1\n     +include::format-patch-caveats.adoc[]\n     +\n      HOOKS\n\nbase-commit: 3e0db84c88c57e70ac8be8c196dfa92c5d656fbc\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535618","messageId":"xmqqikc534mk.fsf@gitster.g","threadId":"64933","inReplyTo":"V2_format-patch_caveats.34b@msgid.xyz","subject":"Re: [PATCH v2] doc: add caveat about roundtripping format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-09T22:59:31Z","receivedAt":"2026-02-09T22:59:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"kristofferhaugsbakk@fastmail.com writes:\n\n> diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n> new file mode 100644\n> index 00000000000..c666d709742\n> --- /dev/null\n> +++ b/Documentation/format-patch-caveats.adoc\n> @@ -0,0 +1,36 @@\n> +Patches produced by linkgit:git-format-patch[1] are inline. This means\n> +that the output from that command can lead to a different commit message\n> +when applied with linkgit:git-am[1]. It can also mean that the patch\n> +that is applied is not the same as the one that was generated, or that\n> +the patch application fails outright.\n> +ifdef::git-am[]\n> +See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n> +endif::git-am[]\n\nIt is news to me that adjective \"inline\" has such a meaning.\n\nWhenever I see somebody writes \"X. This means Y\", I try to see if it\nmakes the result easier to understand to more people by just saying\n\"Y\" without mentioning X, and to me, this is such an occasion.  I'd\nrather see that sentence, plus \"This means\", taken away.\n"},{"id":"535619","messageId":"80bbe45f-2c9e-465f-87aa-c7cb64175ccb@app.fastmail.com","threadId":"64933","inReplyTo":"xmqqikc534mk.fsf@gitster.g","subject":"Re: [PATCH v2] doc: add caveat about roundtripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-09T23:11:00Z","receivedAt":"2026-02-09T23:11:59Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Mon, Feb 9, 2026, at 23:59, Junio C Hamano wrote:\n> kristofferhaugsbakk@fastmail.com writes:\n>\n>> diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n>> new file mode 100644\n>> index 00000000000..c666d709742\n>> --- /dev/null\n>> +++ b/Documentation/format-patch-caveats.adoc\n>> @@ -0,0 +1,36 @@\n>> +Patches produced by linkgit:git-format-patch[1] are inline. This means\n>> +that the output from that command can lead to a different commit message\n>> +when applied with linkgit:git-am[1]. It can also mean that the patch\n>> +that is applied is not the same as the one that was generated, or that\n>> +the patch application fails outright.\n>> +ifdef::git-am[]\n>> +See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n>> +endif::git-am[]\n>\n> It is news to me that adjective \"inline\" has such a meaning.\n\nThe original intent was to emphasize that the commit message and the\npatch being in the same “string” means that there has to be some\ndelimiter. And that can trip things up since there is no escaping.\n\nBut you’re right. This part can be dropped. It is already clear that we\nare talking about delimiters that can occur in the commit message.\n\n>\n> Whenever I see somebody writes \"X. This means Y\", I try to see if it\n> makes the result easier to understand to more people by just saying\n> \"Y\" without mentioning X, and to me, this is such an occasion.  I'd\n> rather see that sentence, plus \"This means\", taken away.\n\nSo write it like this:\n\n    The output from git-patch-format(1) can lead to a different commit\n    message ...\n\nI’ll make that change.\n"},{"id":"535632","messageId":"83b776c4c3b6092f9714adc157ac6a38af1022f7.camel@scientia.org","threadId":"64933","inReplyTo":"format-patch_caveats.281@msgid.xyz","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Christoph Anton Mitterer","fromEmail":"calestyo@scientia.org","sentAt":"2026-02-10T00:53:51Z","receivedAt":"2026-02-10T00:53:56Z","isPatch":true,"sender":{"key":"calestyo@scientia.org","avatar":"https://gravatar.com/avatar/2dd3cd5191e4ec4a5e1e0a0861a64378636270f4007bab080a27b27a607bb267?d=mp&s=160"},"body":"Hey.\n\nWhile it's nice to see it getting documented (thanks for that)...\nwouldn't it be even better to actually fix the underlying issue? :-)\n\nI mean it's all but guaranteed that everyone reads this,... and IMO the\nproblem might even be exploited security wise.\n\nCheers,\nChris.\n"},{"id":"535634","messageId":"CA+P7+xrNycJHTyJwn9AQcJLG0dDAE7KrTvWTHBi+CiQUqK8p5A@mail.gmail.com","threadId":"64933","inReplyTo":"aYoEO0CcVt2Qjgnb@pks.im","subject":"Re: git-am applies commit message diffs","fromName":"Jacob Keller","fromEmail":"jacob.keller@gmail.com","sentAt":"2026-02-10T02:16:35Z","receivedAt":"2026-02-10T02:16:46Z","isPatch":false,"sender":{"key":"jacob.keller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"On Mon, Feb 9, 2026 at 7:59 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> On Fri, Feb 06, 2026 at 04:03:58AM -0500, Jeff King wrote:\n> > On Fri, Feb 06, 2026 at 09:18:50AM +0100, Matthias Beyer wrote:\n> >\n> > > That said, I am no expert in either C or the git codebase at all, but\n> > > from what I saw from reading the git-am codebase, it looks like it tries\n> > > to find the patch by looking for three dashes on a line with a linebreak\n> > > behind (\"---\\n\").\n> >\n> > Yes, that is how the split is made.\n> >\n> > > From what I read, it looks for that from the first line.\n> > > What I would think of here is looking for that \"patchbreak\" from the\n> > > _end_ of the email rather than from the top, that would have prevented\n> > > this issue, right?\n> >\n> > The patch itself may legitimately contain \"---\" on a line by itself (it\n> > would indicate that the line \"--\" was removed from a file). That would\n> > confuse your parser, including in a way that we end up only applying\n> > part of the diff (everything before that fake \"---\" becomes commit\n> > message, and everything after becomes cover-letter material up to the\n> > next \"diff\" line).\n> >\n> > I suspect it also creates corner cases with cover-letter material\n> > (between the \"---\" and the diff itself) that itself contains any \"---\"\n> > marker.\n> >\n> > I don't think there is a way to unambiguously parse the single-stream\n> > output that format-patch produces. This is a reasonably well-known\n> > gotcha (at least around here). E.g., some earlier discussions:\n> >\n> >   2024: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n> >   2022: https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n> >   2015: https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n> >\n> > There are probably more, but it's actually a tricky thing to search for\n> > in the archive, so I stopped digging. ;)\n>\n> Maybe we can't parse it unambiguously. But what we _can_ detect is that\n> a patch is ambiguous in the first place, right? So maybe we could extend\n> git-am(1) to bail by default with a hint that tells the user that:\n>\n\nI think it might make sense in a breaking change to update format\npatch and git am to have an \"unambiguous\" mode which would allow\nsomehow to unambiguously distinguish between commit message contents\nand patch data. I'm not 100% sure how to do this, and it likely\nrequires some sort of breaking changes to both tools to allow\ndistinguishing properly between the two points. Obviously if you're\nsending the contents together, a malicious user could edit the\nformatted patch to move or copy whatever the \"signifier\" for patch vs\ncommit separator is... but at least we'd prevent the cases where\nsomeone accidentally includes diffs without intending to.\n\n>   - They ought to double-check the patch.\n>\n>   - They can override the check with \"--accept-ambiguous-patch\".\n>\n> It at least notifies the user that something potentially-fishy is going\n> on, even though it still shifts the burden onto the person that applies\n> the patch. But I guess that cannot ever be avoided anyway, at least in\n> the general case.\n>\n> Patrick\n\nThese steps also make sense... check the commit content for a diff and\nif we see one, make sure to warn and not allow it by default?\n\nI'm unsure how the receiver end could detect the patch actually is\nunambiguous since multiple different diff hunks can exist to handle\neach file. We could improve the parser to complain about the extra ---\nseparators though?\n"},{"id":"535651","messageId":"20260210064419.GA1756549@coredump.intra.peff.net","threadId":"64933","inReplyTo":"b0c456ce-94f6-4155-8cbd-3dd75a9cc52c@gmail.com","subject":"Re: [PATCH 3/3] templates: detect messages that contain a separator line","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-10T06:44:19Z","receivedAt":"2026-02-10T06:44:23Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 09, 2026 at 10:42:49AM +0000, Phillip Wood wrote:\n\n> > I do it, too, though not all that often. Once upon a time I had a patch\n> > to teach git-commit to auto-convert lines after \"---\" into a note (which\n> > would then be formatted back out via format-patch). But I found for my\n> > git.git workflow that just letting the \"---\" ride along in the commit\n> > object was simpler and easier (since I don't care about having pristine\n> > commit objects, as their ultimate fate is to be dropped in favor of what\n> > is applied upstream).\n> \n> I do it too occasionally. I had planned just to use \"--no-verify\" when I did\n> that but maybe we should just drop this patch. We could make it configurable\n> as Kristoffer suggested, or, as we have the raw message, we could look for a\n> special comment like \"# allow ---\" but I'm not sure I want to spend much\n> more time on this. At least \"---\" only truncates the message rather than\n> applying an unwanted patch.\n\nJust to be clear, I am OK either way, as I do not use the sample\ncommit-msg hook. ;) Since the sample is mostly for illustrative\npurposes, maybe it is fine to potentially over-reach and let people trim\nit as they see fit.\n\n-Peff\n"},{"id":"535652","messageId":"20260210064608.GB1756549@coredump.intra.peff.net","threadId":"64933","inReplyTo":"f5f100de-815e-4bf3-832f-3d473413c635@gmail.com","subject":"Re: [PATCH 0/3] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-10T06:46:08Z","receivedAt":"2026-02-10T06:46:09Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 09, 2026 at 10:43:23AM +0000, Phillip Wood wrote:\n\n> >    2. I'd guess that these days only a small minority of people care\n> >       about sending patches by email. So for most people, a warning about\n> >       their commit message containing a diff or \"---\" will be mostly\n> >       useless, if not outright confusing.\n> \n> People do download patches from github and apply them even if they're not\n> using a email based workflow. I'm not entirely clear but I think that's what\n> happened in the post Matthias linked to. Though if they're using \"patch\"\n> rather than \"git am\" to apply them indenting the diff wont help.\n\nYeah, true. I have done that (thought not very often). I think limiting\nour thinking to \"git am\" in that case is probably OK. We have to draw\nthe line somewhere.\n\n-Peff\n"},{"id":"535653","messageId":"20260210065613.GC1756549@coredump.intra.peff.net","threadId":"64933","inReplyTo":"aYoEO0CcVt2Qjgnb@pks.im","subject":"Re: git-am applies commit message diffs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-10T06:56:13Z","receivedAt":"2026-02-10T06:56:15Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 09, 2026 at 04:58:51PM +0100, Patrick Steinhardt wrote:\n\n> > I don't think there is a way to unambiguously parse the single-stream\n> > output that format-patch produces. This is a reasonably well-known\n> > gotcha (at least around here). E.g., some earlier discussions:\n> > \n> >   2024: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n> >   2022: https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n> >   2015: https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n> > \n> > There are probably more, but it's actually a tricky thing to search for\n> > in the archive, so I stopped digging. ;)\n> \n> Maybe we can't parse it unambiguously. But what we _can_ detect is that\n> a patch is ambiguous in the first place, right? So maybe we could extend\n> git-am(1) to bail by default with a hint that tells the user that:\n> \n>   - They ought to double-check the patch.\n> \n>   - They can override the check with \"--accept-ambiguous-patch\".\n> \n> It at least notifies the user that something potentially-fishy is going\n> on, even though it still shifts the burden onto the person that applies\n> the patch. But I guess that cannot ever be avoided anyway, at least in\n> the general case.\n\nYes, I think you could detect ambiguous cases on the receiving side. You\nmight need some heuristics to reduce false positives, though, since it\nis permitted to include extra content between and after diffs (e.g.,\nformat-patch writes signature lines by default).\n\nSo you'd probably need some rules like:\n\n  - Multiple instances of \"---\" always generate a warning. Though I\n    won't be surprised if it turns out that people often do:\n\n       the commit message\n\n       Signed-off-by: etc...\n       ---\n       Here is some cover letter material.\n\n       ---\n         [diffstat goes here]\n\n    That's totally fine, but indistinguishable from the case that the\n    commit message contains a \"---\" and is being truncated.\n\n  - Presence of \"diff\" header before \"---\", which means there is\n    probably a diff inside the commit message. But then what about when\n    there is no \"---\" at all (as in a non-git patch)? Maybe the rule\n    needs to be \"there is a --- line after a diff header\" or something.\n\n  - Presence of non-empty text lines after a \"diff\" header (but not at\n    the end, which would trigger pointlessly on signature lines). We\n    would never generate this with format-patch, but it is historically\n    allowed. I sometimes use it when talking through a \"something like\n    this...\" patch. I don't expect those to become real commits, but I\n    imagine people do apply them sometimes.\n\nOf course you can sweep all of the false positives under the \"well,\nyou'll have to re-run with --accept-ambiguous-patch\" rug. But we would\nwant to make sure we do not require that often enough to be annoying.\n\n-Peff\n"},{"id":"535666","messageId":"7e6a19c0-332c-40dd-8aee-f6dd9324bcfa@gmail.com","threadId":"64933","inReplyTo":"c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-10T10:57:28Z","receivedAt":"2026-02-10T10:57:31Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Kristoffer\n\nOn 09/02/2026 17:59, Kristoffer Haugsbakk wrote:\n> Hi Phillip\n> On Mon, Feb 9, 2026, at 17:42, Phillip Wood wrote:\n>> On 08/02/2026 00:11, kristofferhaugsbakk@fastmail.com wrote:\n>>> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>>>\n>>> [snip]\n>>> +Patches produced by linkgit:git-format-patch[1] or\n>>> +linkgit:git-send-email[1] are inline. This means that the output of\n>>> +these two commands can lead to a different commit message when applied\n>>> +with linkgit:git-am[1]. It can also mean that the patch is not applied\n>>> +correctly.\n>>\n>> Is this last sentence referring to diffs in the commit message being\n>> applied? I don't think there are circumstances where the patch itself is\n>> not applied correctly.\n> \n> I tested with a line like\n> \n>      Index x\n> \n> Yesterday and got an empty patch when running git-am(1). But I couldn’t\n> reproduce now. I must have made a mistake.\n\nOh, if you use \"Index: x\" (with a colon) does that mess up the patch \napplication?\n\n> \n> I think this should be changed to:\n> \n>      It can also mean that the patch that is applied is not the same as\n>      the one that was generated.\n\nThat's a nice concise way of putting it\n\n> \n> (generated = shorthand for made by git-format-patch(1))\n> \n> This sentence would then serve as an introduction for the “Furthermore,”\n> paragraph later.\n> \n>>> [snip]\n>>> +----\n>>> +```\n>>> +diff ...\n>>> +```\n>>> +----\n>>\n>> I'm not sure the markdown really adds anything here\n> \n> I don’t understand? It demonstrates a markup for code which does not use\n> indentation.\n\nBut I think the markup is a distraction from the problem which is that \nthe diff is not indented. Also calling it \"Github MarkDown\" is \nunfortunate as we try not to favor one forge over another and many sites \nsupport that syntax.\n\n\nThanks\n\nPhillip\n\n> Well, maybe it should be:\n> \n>      ----\n>      ```\n>      diff ...\n>      ...\n>      ```\n>      ----\n> \n> Or maybe...\n> \n>      ----\n>      ```\n>      diff --git a/example.txt b/example.txt\n>      ...\n>      ```\n>      ----\n> \n> I’m leaning towards the latter.\n> \n>>> [snip]\n>>> +One might want to use a general-purpose utility like patch(1) instead,\n>>\n>> \"Given these limitations, one might be tempted to ...\"?\n> \n> That’s good. That leads with the problem instead letting it trail off at\n> the end of the sentence. I’ll use that.\n> \n>>> +given these limitations. However, patch(1) will not only look for\n>>> +unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n>>> +diffs as well.\n>>\n>> This is useful context.\n>>\n>> Thanks\n>>\n>> Phillip\n> \n> Thanks for taking a look. It’s always appreciated.\n\n"},{"id":"535667","messageId":"45be48a0-a656-4f1c-8613-6486e7ad3c40@gmail.com","threadId":"64933","inReplyTo":"V2_format-patch_caveats.34b@msgid.xyz","subject":"Re: [PATCH v2] doc: add caveat about roundtripping format-patch","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-10T11:02:27Z","receivedAt":"2026-02-10T11:02:31Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Kristoffer\n\nThis looks good to me modulo the comments about \"Github MarkDown\" I \nmentioned in my other mail.\n\nThanks for working on this, it is a nice improvement to our documentation.\n\nPhillip\n\nOn 09/02/2026 22:37, kristofferhaugsbakk@fastmail.com wrote:\n> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> \n> git-format-patch(1) and git-am(1) deal with formatting commits as\n> patches and applying them, respectively. Naturally they use a few\n> delimiters to mark where the commit message ends. This can lead to\n> surprising behavior when these delimiters are used in the commit\n> message itself.\n> \n> git-format-patch(1) will accept any commit message and not warn or error\n> about these delimiters being used.[1]\n> \n> Especially problematic is the presence of unindented diffs in the commit\n> message; the patch machinery will naturally (since the commit message\n> has ended) try to apply that diff and everything after it.[2]\n> \n> It is unclear whether any commands in this chain will learn to warn\n> about this. One concern could be that users have learned to rely on\n> the three-dash line rule to conveniently add extra-commit message\n> information in the commit message, knowing that git-am(1) will\n> ignore it.[4]\n> \n> All of this is covered already, technically. However, we should spell\n> out the implications.\n> \n> † 1: There is also git-commit(1) to consider. However, making that\n>       command warn or error out over such delimiters would be disruptive\n>       to all Git users who never use email in their workflow.\n> † 2: Recently patch(1) caused this issue for a project, but it was noted\n>       that git-am(1) has the same behavior[3]\n> † 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n> † 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n>       https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\n> \n> Reported-by: Matthias Beyer <mail@beyermatthias.de>\n> Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n> Reported-by: Matheus Tavares <matheus.tavb@gmail.com>\n> Reported-by: Chris Packham <judge.packham@gmail.com>\n> Helped-by: Jakob Haufe <sur5r@sur5r.net>\n> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> \n> ---\n> \n> v2:\n> \n> Address feedback from Phillip Wood.\n> \n> Cc: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> • Drop the code blocks with the diffs; the prose speaks for itself, no need\n>    to take up space\n> • Don’t discuss git-send-email(1). We already know that git-format-patch(1)\n>    is the generator. It is mentioned in git-send-email(1).\n> • Try to be more clear about the case where someone might be applying a\n>    diff. Use the example from Matthias Beyer in:\n> \n>        https://lore.kernel.org/git/gfxpnecn2cdtmeiape2d4x5aybuyyqi4c7m6te3khgct34dd44@wqusigna2nsp/\n> \n>    Hopefully I explained it correctly?\n> • Add a “this goes to show...”... which seems to emphasize the point\n>    without being redundant. Hopefully.\n> \n> Try to address feedback from Junio C Hamano by adding more nuance: the diff\n> in the commit message might be applied as well, or the patch machinery\n> might trip on something and fail.\n> \n> Finally, in the middle of discussing the three possible cmt. message\n> delimiters, I noticed that the three points were drifting apart. So I\n> decided to use the list already used in git-am(1) and be done with it in\n> one place.\n> \n> ---\n> \n> It seems that the section break in git-format-patch(1) does not get\n> applied in the man output (according to `Documentation/doc-diff`\n> apparently)? Maybe this is the wrong construct? I couldn’t find any\n> other thematic breaks here (though there are several variations).\n> ---\n>   Documentation/format-patch-caveats.adoc       | 36 +++++++++++++++++++\n>   .../format-patch-end-of-commit-message.adoc   |  3 ++\n>   Documentation/git-am.adoc                     | 15 ++++++--\n>   Documentation/git-format-patch.adoc           |  4 +++\n>   Documentation/git-send-email.adoc             |  5 +++\n>   5 files changed, 60 insertions(+), 3 deletions(-)\n>   create mode 100644 Documentation/format-patch-caveats.adoc\n>   create mode 100644 Documentation/format-patch-end-of-commit-message.adoc\n> \n> diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n> new file mode 100644\n> index 00000000000..c666d709742\n> --- /dev/null\n> +++ b/Documentation/format-patch-caveats.adoc\n> @@ -0,0 +1,36 @@\n> +Patches produced by linkgit:git-format-patch[1] are inline. This means\n> +that the output from that command can lead to a different commit message\n> +when applied with linkgit:git-am[1]. It can also mean that the patch\n> +that is applied is not the same as the one that was generated, or that\n> +the patch application fails outright.\n> +ifdef::git-am[]\n> +See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n> +endif::git-am[]\n> +\n> +ifndef::git-am[]\n> +Any line that is of the form:\n> +\n> +include::format-patch-end-of-commit-message.adoc[]\n> +\n> +will terminate the commit message and cause the patch machinery to start\n> +searching for patches to apply.\n> +endif::git-am[]\n> +\n> +Note that this is especially problematic for unindented diffs that occur\n> +in the commit message; the diff in the commit message might get applied\n> +along with the patch section, or the patch application machinery might\n> +trip up because the patch target doesn't apply. This could for example\n> +be caused by a diff in a GitHub Markdown code block.\n> +\n> +This loss of fidelity might be simple to notice if you are applying\n> +patches directly from a mailbox. However, changes originating from Git\n> +could be applied in bulk, in which case this would be much harder to\n> +notice. This could for example be a Linux distribution which uses patch\n> +files to apply changes on top of the commits from the upstream\n> +repositories. This goes to show that this behavior does not only impact\n> +email workflows.\n> +\n> +Given these limitations, one might be tempted to use a general-purpose\n> +utility like patch(1) instead. However, patch(1) will not only look for\n> +unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n> +diffs as well.\n> diff --git a/Documentation/format-patch-end-of-commit-message.adoc b/Documentation/format-patch-end-of-commit-message.adoc\n> new file mode 100644\n> index 00000000000..47399ae7266\n> --- /dev/null\n> +++ b/Documentation/format-patch-end-of-commit-message.adoc\n> @@ -0,0 +1,3 @@\n> +* three-dashes and end-of-line, or\n> +* a line that begins with \"diff -\", or\n> +* a line that begins with \"Index: \"\n> diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\n> index 0c94776e296..756dfd722b9 100644\n> --- a/Documentation/git-am.adoc\n> +++ b/Documentation/git-am.adoc\n> @@ -231,10 +231,11 @@ applying.\n>   --allow-empty::\n>   \tAfter a patch failure on an input e-mail message lacking a patch,\n>   \tcreate an empty commit with the contents of the e-mail message\n>   \tas its log message.\n>   \n> +[[discussion]]\n>   DISCUSSION\n>   ----------\n>   \n>   The commit author name is taken from the \"From: \" line of the\n>   message, and commit author date is taken from the \"Date: \" line\n> @@ -252,17 +253,18 @@ where the patch begins.  Excess whitespace at the end of each\n>   line is automatically stripped.\n>   \n>   The patch is expected to be inline, directly following the\n>   message.  Any line that is of the form:\n>   \n> -* three-dashes and end-of-line, or\n> -* a line that begins with \"diff -\", or\n> -* a line that begins with \"Index: \"\n> +include::format-patch-end-of-commit-message.adoc[]\n>   \n>   is taken as the beginning of a patch, and the commit log message\n>   is terminated before the first occurrence of such a line.\n>   \n> +This means that the contents of the commit message can inadvertently\n> +interrupt the processing (see the <<caveats,CAVEATS>> section below).\n> +\n>   When initially invoking `git am`, you give it the names of the mailboxes\n>   to process.  Upon seeing the first patch that does not apply, it\n>   aborts in the middle.  You can recover from this in one of two ways:\n>   \n>   . skip the current patch by re-running the command with the `--skip`\n> @@ -281,10 +283,17 @@ Before any patches are applied, ORIG_HEAD is set to the tip of the\n>   current branch.  This is useful if you have problems with multiple\n>   commits, like running 'git am' on the wrong branch or an error in the\n>   commits that is more easily fixed by changing the mailbox (e.g.\n>   errors in the \"From:\" lines).\n>   \n> +[[caveats]]\n> +CAVEATS\n> +-------\n> +\n> +:git-am: 1\n> +include::format-patch-caveats.adoc[]\n> +\n>   HOOKS\n>   -----\n>   This command can run `applypatch-msg`, `pre-applypatch`,\n>   and `post-applypatch` hooks.  See linkgit:githooks[5] for more\n>   information.\n> diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\n> index 9a7807ca71a..36851aaf5e1 100644\n> --- a/Documentation/git-format-patch.adoc\n> +++ b/Documentation/git-format-patch.adoc\n> @@ -796,10 +796,14 @@ CAVEATS\n>   Note that `format-patch` will omit merge commits from the output, even\n>   if they are part of the requested range. A simple \"patch\" does not\n>   include enough information for the receiving end to reproduce the same\n>   merge commit.\n>   \n> +'''\n> +\n> +include::format-patch-caveats.adoc[]\n> +\n>   SEE ALSO\n>   --------\n>   linkgit:git-am[1], linkgit:git-send-email[1]\n>   \n>   GIT\n> diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc\n> index ebe8853e9f5..0b118df6498 100644\n> --- a/Documentation/git-send-email.adoc\n> +++ b/Documentation/git-send-email.adoc\n> @@ -690,10 +690,15 @@ Links of a few such community maintained helpers are:\n>   \t  (cross platform client that can send emails using the ProtonMail API)\n>   \n>   \t- https://github.com/AdityaGarg8/git-credential-email[git-msgraph]\n>   \t  (cross platform client that can send emails using the Microsoft Graph API)\n>   \n> +CAVEATS\n> +-------\n> +\n> +include::format-patch-caveats.adoc[]\n> +\n>   SEE ALSO\n>   --------\n>   linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)\n>   \n>   GIT\n> \n> Interdiff against v1:\n>    diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n>    index 2accf2763fd..c666d709742 100644\n>    --- a/Documentation/format-patch-caveats.adoc\n>    +++ b/Documentation/format-patch-caveats.adoc\n>    @@ -1,39 +1,36 @@\n>    -Patches produced by linkgit:git-format-patch[1] or\n>    -linkgit:git-send-email[1] are inline. This means that the output of\n>    -these two commands can lead to a different commit message when applied\n>    -with linkgit:git-am[1]. It can also mean that the patch is not applied\n>    -correctly.\n>    +Patches produced by linkgit:git-format-patch[1] are inline. This means\n>    +that the output from that command can lead to a different commit message\n>    +when applied with linkgit:git-am[1]. It can also mean that the patch\n>    +that is applied is not the same as the one that was generated, or that\n>    +the patch application fails outright.\n>    +ifdef::git-am[]\n>    +See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n>    +endif::git-am[]\n>     \n>    -The commit message might contain a three-dash line (`---`) which was\n>    -perhaps meant to be a thematic break. That means that the commit message\n>    -will be cut short. The presence of a line starting with \"Index: \" can\n>    -cause the patch not to be found, giving an error about an empty patch.\n>    +ifndef::git-am[]\n>    +Any line that is of the form:\n>     \n>    -Furthermore, the presence of an unindented diff in the commit message\n>    -will not only cut the message short but cause that very diff to be\n>    -applied, along with the patch in the patch section. The commit message\n>    -might for example have a diff in a GitHub MarkDown code fence:\n>    +include::format-patch-end-of-commit-message.adoc[]\n>     \n>    -----\n>    -```\n>    -diff ...\n>    -```\n>    -----\n>    +will terminate the commit message and cause the patch machinery to start\n>    +searching for patches to apply.\n>    +endif::git-am[]\n>     \n>    -The solution for this is to indent the diff instead:\n>    -\n>    -----\n>    -    diff ...\n>    -----\n>    +Note that this is especially problematic for unindented diffs that occur\n>    +in the commit message; the diff in the commit message might get applied\n>    +along with the patch section, or the patch application machinery might\n>    +trip up because the patch target doesn't apply. This could for example\n>    +be caused by a diff in a GitHub Markdown code block.\n>     \n>     This loss of fidelity might be simple to notice if you are applying\n>    -patches directly from a mailbox. However, a commit authored long ago\n>    -might be applied in a different context, perhaps because many changes\n>    -are being integrated via patch files and the\n>    -linkgit:git-format-patch[1] format is trusted to import changes of a\n>    -Git origin.\n>    +patches directly from a mailbox. However, changes originating from Git\n>    +could be applied in bulk, in which case this would be much harder to\n>    +notice. This could for example be a Linux distribution which uses patch\n>    +files to apply changes on top of the commits from the upstream\n>    +repositories. This goes to show that this behavior does not only impact\n>    +email workflows.\n>     \n>    -One might want to use a general-purpose utility like patch(1) instead,\n>    -given these limitations. However, patch(1) will not only look for\n>    +Given these limitations, one might be tempted to use a general-purpose\n>    +utility like patch(1) instead. However, patch(1) will not only look for\n>     unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n>     diffs as well.\n>    diff --git a/Documentation/format-patch-end-of-commit-message.adoc b/Documentation/format-patch-end-of-commit-message.adoc\n>    new file mode 100644\n>    index 00000000000..47399ae7266\n>    --- /dev/null\n>    +++ b/Documentation/format-patch-end-of-commit-message.adoc\n>    @@ -0,0 +1,3 @@\n>    +* three-dashes and end-of-line, or\n>    +* a line that begins with \"diff -\", or\n>    +* a line that begins with \"Index: \"\n>    diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\n>    index 18f5b950825..756dfd722b9 100644\n>    --- a/Documentation/git-am.adoc\n>    +++ b/Documentation/git-am.adoc\n>    @@ -231,10 +231,11 @@ applying.\n>     --allow-empty::\n>     \tAfter a patch failure on an input e-mail message lacking a patch,\n>     \tcreate an empty commit with the contents of the e-mail message\n>     \tas its log message.\n>     \n>    +[[discussion]]\n>     DISCUSSION\n>     ----------\n>     \n>     The commit author name is taken from the \"From: \" line of the\n>     message, and commit author date is taken from the \"Date: \" line\n>    @@ -252,18 +253,16 @@ where the patch begins.  Excess whitespace at the end of each\n>     line is automatically stripped.\n>     \n>     The patch is expected to be inline, directly following the\n>     message.  Any line that is of the form:\n>     \n>    -* three-dashes and end-of-line, or\n>    -* a line that begins with \"diff -\", or\n>    -* a line that begins with \"Index: \"\n>    +include::format-patch-end-of-commit-message.adoc[]\n>     \n>     is taken as the beginning of a patch, and the commit log message\n>     is terminated before the first occurrence of such a line.\n>     \n>    -This means that the content of the commit message can inadverently\n>    +This means that the contents of the commit message can inadvertently\n>     interrupt the processing (see the <<caveats,CAVEATS>> section below).\n>     \n>     When initially invoking `git am`, you give it the names of the mailboxes\n>     to process.  Upon seeing the first patch that does not apply, it\n>     aborts in the middle.  You can recover from this in one of two ways:\n>    @@ -288,10 +287,11 @@ errors in the \"From:\" lines).\n>     \n>     [[caveats]]\n>     CAVEATS\n>     -------\n>     \n>    +:git-am: 1\n>     include::format-patch-caveats.adoc[]\n>     \n>     HOOKS\n>     -----\n>     This command can run `applypatch-msg`, `pre-applypatch`,\n> \n> Range-diff against v1:\n> 1:  4bed8f55b98 ! 1:  c54f394bb33 doc: add caveat about roundtripping format-patch\n>      @@ Metadata\n>        ## Commit message ##\n>           doc: add caveat about roundtripping format-patch\n>       \n>      -    git-format-patch(1), git-send-email(1), and git-am(1) deal with\n>      -    formatting commits as patches, sending them (perhaps directly), and\n>      -    applying them, respectively. Naturally they use a few delimiters to mark\n>      -    where the commit message ends. This can lead to surprising behavior when\n>      -    these delimiters are used in the commit message itself.\n>      +    git-format-patch(1) and git-am(1) deal with formatting commits as\n>      +    patches and applying them, respectively. Naturally they use a few\n>      +    delimiters to mark where the commit message ends. This can lead to\n>      +    surprising behavior when these delimiters are used in the commit\n>      +    message itself.\n>       \n>      -    git-format-patch(1) and git-send-email(1) will accept any commit message\n>      -    and not warn or error about these delimiters being used.[1]\n>      +    git-format-patch(1) will accept any commit message and not warn or error\n>      +    about these delimiters being used.[1]\n>       \n>      -    Moreover, the presence of unindented diffs in the commit message will\n>      -    cause git-am(1) to apply both the diffs from the commit message as well\n>      -    as the patch section.[2]\n>      +    Especially problematic is the presence of unindented diffs in the commit\n>      +    message; the patch machinery will naturally (since the commit message\n>      +    has ended) try to apply that diff and everything after it.[2]\n>       \n>           It is unclear whether any commands in this chain will learn to warn\n>           about this. One concern could be that users have learned to rely on\n>      @@ Commit message\n>           information in the commit message, knowing that git-am(1) will\n>           ignore it.[4]\n>       \n>      -    All of this is covered already, technically, However, we should spell\n>      +    All of this is covered already, technically. However, we should spell\n>           out the implications.\n>       \n>           † 1: There is also git-commit(1) to consider. However, making that\n>                command warn or error out over such delimiters would be disruptive\n>                to all Git users who never use email in their workflow.\n>      -    [2]: Recently patch(1) caused this issue for a project, but it was noted\n>      +    † 2: Recently patch(1) caused this issue for a project, but it was noted\n>                that git-am(1) has the same behavior[3]\n>      -    [3]: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n>      -    [4]: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n>      +    † 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n>      +    † 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n>      +         https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\n>       \n>           Reported-by: Matthias Beyer <mail@beyermatthias.de>\n>           Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n>      @@ Commit message\n>           Helped-by: Jakob Haufe <sur5r@sur5r.net>\n>           Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>       \n>      +    ---\n>      +\n>      +    v2:\n>      +\n>      +    Address feedback from Phillip Wood.\n>      +\n>      +    Cc: Phillip Wood <phillip.wood@dunelm.org.uk>\n>      +\n>      +    • Drop the code blocks with the diffs; the prose speaks for itself, no need\n>      +      to take up space\n>      +    • Don’t discuss git-send-email(1). We already know that git-format-patch(1)\n>      +      is the generator. It is mentioned in git-send-email(1).\n>      +    • Try to be more clear about the case where someone might be applying a\n>      +      diff. Use the example from Matthias Beyer in:\n>      +\n>      +          https://lore.kernel.org/git/gfxpnecn2cdtmeiape2d4x5aybuyyqi4c7m6te3khgct34dd44@wqusigna2nsp/\n>      +\n>      +      Hopefully I explained it correctly?\n>      +    • Add a “this goes to show...”... which seems to emphasize the point\n>      +      without being redundant. Hopefully.\n>      +\n>      +    Try to address feedback from Junio C Hamano by adding more nuance: the diff\n>      +    in the commit message might be applied as well, or the patch machinery\n>      +    might trip on something and fail.\n>      +\n>      +    Finally, in the middle of discussing the three possible cmt. message\n>      +    delimiters, I noticed that the three points were drifting apart. So I\n>      +    decided to use the list already used in git-am(1) and be done with it in\n>      +    one place.\n>      +\n>      +    ---\n>      +\n>      +    It seems that the section break in git-format-patch(1) does not get\n>      +    applied in the man output (according to `Documentation/doc-diff`\n>      +    apparently)? Maybe this is the wrong construct? I couldn’t find any\n>      +    other thematic breaks here (though there are several variations).\n>      +\n>        ## Documentation/format-patch-caveats.adoc (new) ##\n>       @@\n>      -+Patches produced by linkgit:git-format-patch[1] or\n>      -+linkgit:git-send-email[1] are inline. This means that the output of\n>      -+these two commands can lead to a different commit message when applied\n>      -+with linkgit:git-am[1]. It can also mean that the patch is not applied\n>      -+correctly.\n>      -+\n>      -+The commit message might contain a three-dash line (`---`) which was\n>      -+perhaps meant to be a thematic break. That means that the commit message\n>      -+will be cut short. The presence of a line starting with \"Index: \" can\n>      -+cause the patch not to be found, giving an error about an empty patch.\n>      ++Patches produced by linkgit:git-format-patch[1] are inline. This means\n>      ++that the output from that command can lead to a different commit message\n>      ++when applied with linkgit:git-am[1]. It can also mean that the patch\n>      ++that is applied is not the same as the one that was generated, or that\n>      ++the patch application fails outright.\n>      ++ifdef::git-am[]\n>      ++See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n>      ++endif::git-am[]\n>       +\n>      -+Furthermore, the presence of an unindented diff in the commit message\n>      -+will not only cut the message short but cause that very diff to be\n>      -+applied, along with the patch in the patch section. The commit message\n>      -+might for example have a diff in a GitHub MarkDown code fence:\n>      ++ifndef::git-am[]\n>      ++Any line that is of the form:\n>       +\n>      -+----\n>      -+```\n>      -+diff ...\n>      -+```\n>      -+----\n>      ++include::format-patch-end-of-commit-message.adoc[]\n>       +\n>      -+The solution for this is to indent the diff instead:\n>      ++will terminate the commit message and cause the patch machinery to start\n>      ++searching for patches to apply.\n>      ++endif::git-am[]\n>       +\n>      -+----\n>      -+    diff ...\n>      -+----\n>      ++Note that this is especially problematic for unindented diffs that occur\n>      ++in the commit message; the diff in the commit message might get applied\n>      ++along with the patch section, or the patch application machinery might\n>      ++trip up because the patch target doesn't apply. This could for example\n>      ++be caused by a diff in a GitHub Markdown code block.\n>       +\n>       +This loss of fidelity might be simple to notice if you are applying\n>      -+patches directly from a mailbox. However, a commit authored long ago\n>      -+might be applied in a different context, perhaps because many changes\n>      -+are being integrated via patch files and the\n>      -+linkgit:git-format-patch[1] format is trusted to import changes of a\n>      -+Git origin.\n>      ++patches directly from a mailbox. However, changes originating from Git\n>      ++could be applied in bulk, in which case this would be much harder to\n>      ++notice. This could for example be a Linux distribution which uses patch\n>      ++files to apply changes on top of the commits from the upstream\n>      ++repositories. This goes to show that this behavior does not only impact\n>      ++email workflows.\n>       +\n>      -+One might want to use a general-purpose utility like patch(1) instead,\n>      -+given these limitations. However, patch(1) will not only look for\n>      ++Given these limitations, one might be tempted to use a general-purpose\n>      ++utility like patch(1) instead. However, patch(1) will not only look for\n>       +unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n>       +diffs as well.\n>       \n>      + ## Documentation/format-patch-end-of-commit-message.adoc (new) ##\n>      +@@\n>      ++* three-dashes and end-of-line, or\n>      ++* a line that begins with \"diff -\", or\n>      ++* a line that begins with \"Index: \"\n>      +\n>        ## Documentation/git-am.adoc ##\n>      -@@ Documentation/git-am.adoc: message.  Any line that is of the form:\n>      +@@ Documentation/git-am.adoc: applying.\n>      + \tcreate an empty commit with the contents of the e-mail message\n>      + \tas its log message.\n>      +\n>      ++[[discussion]]\n>      + DISCUSSION\n>      + ----------\n>      +\n>      +@@ Documentation/git-am.adoc: line is automatically stripped.\n>      + The patch is expected to be inline, directly following the\n>      + message.  Any line that is of the form:\n>      +\n>      +-* three-dashes and end-of-line, or\n>      +-* a line that begins with \"diff -\", or\n>      +-* a line that begins with \"Index: \"\n>      ++include::format-patch-end-of-commit-message.adoc[]\n>      +\n>        is taken as the beginning of a patch, and the commit log message\n>        is terminated before the first occurrence of such a line.\n>        \n>      -+This means that the content of the commit message can inadverently\n>      ++This means that the contents of the commit message can inadvertently\n>       +interrupt the processing (see the <<caveats,CAVEATS>> section below).\n>       +\n>        When initially invoking `git am`, you give it the names of the mailboxes\n>      @@ Documentation/git-am.adoc: commits, like running 'git am' on the wrong branch or\n>       +CAVEATS\n>       +-------\n>       +\n>      ++:git-am: 1\n>       +include::format-patch-caveats.adoc[]\n>       +\n>        HOOKS\n> \n> base-commit: 3e0db84c88c57e70ac8be8c196dfa92c5d656fbc\n\n"},{"id":"535679","messageId":"aYs_P8QujA6mL81-@pks.im","threadId":"64933","inReplyTo":"CA+P7+xrNycJHTyJwn9AQcJLG0dDAE7KrTvWTHBi+CiQUqK8p5A@mail.gmail.com","subject":"Re: git-am applies commit message diffs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-02-10T14:22:55Z","receivedAt":"2026-02-10T14:23:02Z","isPatch":false,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Feb 09, 2026 at 06:16:35PM -0800, Jacob Keller wrote:\n> On Mon, Feb 9, 2026 at 7:59 AM Patrick Steinhardt <ps@pks.im> wrote:\n> >\n> > On Fri, Feb 06, 2026 at 04:03:58AM -0500, Jeff King wrote:\n> > > On Fri, Feb 06, 2026 at 09:18:50AM +0100, Matthias Beyer wrote:\n> > >\n> > > > That said, I am no expert in either C or the git codebase at all, but\n> > > > from what I saw from reading the git-am codebase, it looks like it tries\n> > > > to find the patch by looking for three dashes on a line with a linebreak\n> > > > behind (\"---\\n\").\n> > >\n> > > Yes, that is how the split is made.\n> > >\n> > > > From what I read, it looks for that from the first line.\n> > > > What I would think of here is looking for that \"patchbreak\" from the\n> > > > _end_ of the email rather than from the top, that would have prevented\n> > > > this issue, right?\n> > >\n> > > The patch itself may legitimately contain \"---\" on a line by itself (it\n> > > would indicate that the line \"--\" was removed from a file). That would\n> > > confuse your parser, including in a way that we end up only applying\n> > > part of the diff (everything before that fake \"---\" becomes commit\n> > > message, and everything after becomes cover-letter material up to the\n> > > next \"diff\" line).\n> > >\n> > > I suspect it also creates corner cases with cover-letter material\n> > > (between the \"---\" and the diff itself) that itself contains any \"---\"\n> > > marker.\n> > >\n> > > I don't think there is a way to unambiguously parse the single-stream\n> > > output that format-patch produces. This is a reasonably well-known\n> > > gotcha (at least around here). E.g., some earlier discussions:\n> > >\n> > >   2024: https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n> > >   2022: https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n> > >   2015: https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n> > >\n> > > There are probably more, but it's actually a tricky thing to search for\n> > > in the archive, so I stopped digging. ;)\n> >\n> > Maybe we can't parse it unambiguously. But what we _can_ detect is that\n> > a patch is ambiguous in the first place, right? So maybe we could extend\n> > git-am(1) to bail by default with a hint that tells the user that:\n> >\n> \n> I think it might make sense in a breaking change to update format\n> patch and git am to have an \"unambiguous\" mode which would allow\n> somehow to unambiguously distinguish between commit message contents\n> and patch data. I'm not 100% sure how to do this, and it likely\n> requires some sort of breaking changes to both tools to allow\n> distinguishing properly between the two points.\n\nThat is worth a thought indeed. I guess one of the biggest questions\nhere is whether we can introduce such an unambiguous mode in such a way\nthat old Git clients/patch(1) would continue to understand them. I\nwouldn't mind much if they would still misinterpret the ambiguous parts.\nBut if so, we could make this unambiguous mode the default without a\nbreaking change.\n\nThis is all pure speculation though, I have no idea whether such a\nbackwards-compatible and forwards-safe mode exists.\n\n> Obviously if you're sending the contents together, a malicious user\n> could edit the formatted patch to move or copy whatever the\n> \"signifier\" for patch vs commit separator is... but at least we'd\n> prevent the cases where someone accidentally includes diffs without\n> intending to.\n\nWell, if we had such an unambiguous mode I would say that eventually,\nGit should start to refuse patches that have been generated without this\nmode by default.\n\nPatrick\n"},{"id":"535685","messageId":"xmqq34381tze.fsf@gitster.g","threadId":"64933","inReplyTo":"aYs_P8QujA6mL81-@pks.im","subject":"Re: git-am applies commit message diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-10T15:47:01Z","receivedAt":"2026-02-10T15:47:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> That is worth a thought indeed. I guess one of the biggest questions\n> here is whether we can introduce such an unambiguous mode in such a way\n> that old Git clients/patch(1) would continue to understand them. I\n> wouldn't mind much if they would still misinterpret the ambiguous parts.\n> But if so, we could make this unambiguous mode the default without a\n> breaking change.\n\nYup, if the old versions misinterpret exactly the same way as\nbefore, then it does not even have to be called \"unambiguous mode\"\nthat is on by default.  I doubt it is possible, though.\n\n>> Obviously if you're sending the contents together, a malicious user\n>> could edit the formatted patch to move or copy whatever the\n>> \"signifier\" for patch vs commit separator is... but at least we'd\n>> prevent the cases where someone accidentally includes diffs without\n>> intending to.\n>\n> Well, if we had such an unambiguous mode I would say that eventually,\n> Git should start to refuse patches that have been generated without this\n> mode by default.\n\nOr any unsigned patch, perhaps?\n"},{"id":"535687","messageId":"7ef28209-9953-4593-b1ce-11af5e8375bd@app.fastmail.com","threadId":"64933","inReplyTo":"83b776c4c3b6092f9714adc157ac6a38af1022f7.camel@scientia.org","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-10T16:00:07Z","receivedAt":"2026-02-10T16:00:29Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"Hi\n\nOn Tue, Feb 10, 2026, at 01:53, Christoph Anton Mitterer wrote:\n> While it's nice to see it getting documented (thanks for that)...\n> wouldn't it be even better to actually fix the underlying issue? :-)\n>\n> I mean it's all but guaranteed that everyone reads this,... and IMO the\n> problem might even be exploited security wise.\n\nThere’s a discussion about fixing it from the start of the thread:\n\nhttps://lore.kernel.org/git/bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm/\n\nPlease use Reply-All. ;)\n"},{"id":"535688","messageId":"64649b1c-d3c8-42f1-b176-27f3fe8b6e46@app.fastmail.com","threadId":"64933","inReplyTo":"7e6a19c0-332c-40dd-8aee-f6dd9324bcfa@gmail.com","subject":"Re: [PATCH] doc: add caveat about roundtripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"code@khaugsbakk.name","sentAt":"2026-02-10T16:00:26Z","receivedAt":"2026-02-10T16:00:49Z","isPatch":true,"sender":{"key":"code@khaugsbakk.name","avatar":"https://avatars.githubusercontent.com/u/2229597?v=4"},"body":"On Tue, Feb 10, 2026, at 11:57, Phillip Wood wrote:\n>>>[snip]\n>>> Is this last sentence referring to diffs in the commit message being\n>>> applied? I don't think there are circumstances where the patch itself is\n>>> not applied correctly.\n>>\n>> I tested with a line like\n>>\n>>      Index x\n>>\n>> Yesterday and got an empty patch when running git-am(1). But I couldn’t\n>> reproduce now. I must have made a mistake.\n>\n> Oh, if you use \"Index: x\" (with a colon) does that mess up the patch\n> application?\n\nSorry, I think I made a typo. I did test with something like `Index:\nsomething`. I’m pretty sure I did...\n\nBut now I’ve taken the description from git-am(1) for the\ndelimiters. I’ve moved away from trying to explain each case.\n\n>>[snip]\n>> I don’t understand? It demonstrates a markup for code which does not use\n>> indentation.\n>\n> But I think the markup is a distraction from the problem which is that\n> the diff is not indented.\n\nI’ve dropped the code blocks in v2 since you don’t need a code block to\nshow indentation. Or code fences.\n\n> Also calling it \"Github MarkDown\" is unfortunate as we try not to\n> favor one forge over another and many sites support that syntax.\n\nSure. I can just say MarkDown code fence. Such a code fence does not use\nindentation so it’s clear that we are contrasting with the MD\nalternative of just indentation.\n\nThanks!\n"},{"id":"535697","messageId":"cd125186-dd81-43dd-a7f6-388b683d01ca@app.fastmail.com","threadId":"64933","inReplyTo":"V2_format-patch_caveats.34b@msgid.xyz","subject":"Re: [PATCH v2] doc: add caveat about roundtripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"code@khaugsbakk.name","sentAt":"2026-02-10T18:20:38Z","receivedAt":"2026-02-10T18:23:57Z","isPatch":true,"sender":{"key":"code@khaugsbakk.name","avatar":"https://avatars.githubusercontent.com/u/2229597?v=4"},"body":"Snipping all my verbiage here.\n\nOn Mon, Feb 9, 2026, at 23:37, kristofferhaugsbakk@fastmail.com wrote:\n>[snip]\n> @@ -796,10 +796,14 @@ CAVEATS\n>  Note that `format-patch` will omit merge commits from the output, even\n>  if they are part of the requested range. A simple \"patch\" does not\n>  include enough information for the receiving end to reproduce the same\n>  merge commit.\n>\n> +'''\n> +\n> +include::format-patch-caveats.adoc[]\n> +\n>  SEE ALSO\n>  --------\n>[snip]\n>     +\n>     +    It seems that the section break in git-format-patch(1) does not get\n>     +    applied in the man output (according to `Documentation/doc-diff`\n>     +    apparently)? Maybe this is the wrong construct? I couldn’t find any\n>     +    other thematic breaks here (though there are several variations).\n>     +\n>[snip]\n\nI want to use a heading instead.\n\n    === Patch application\n"},{"id":"535730","messageId":"CA+P7+xo0-9h_V8xGQaEdgBEaxjrbrNOdPfmFmhKup+Z-7w0zUw@mail.gmail.com","threadId":"64933","inReplyTo":"xmqq34381tze.fsf@gitster.g","subject":"Re: git-am applies commit message diffs","fromName":"Jacob Keller","fromEmail":"jacob.keller@gmail.com","sentAt":"2026-02-11T02:31:23Z","receivedAt":"2026-02-11T02:31:34Z","isPatch":false,"sender":{"key":"jacob.keller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"On Tue, Feb 10, 2026 at 7:47 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Patrick Steinhardt <ps@pks.im> writes:\n>\n> > That is worth a thought indeed. I guess one of the biggest questions\n> > here is whether we can introduce such an unambiguous mode in such a way\n> > that old Git clients/patch(1) would continue to understand them. I\n> > wouldn't mind much if they would still misinterpret the ambiguous parts.\n> > But if so, we could make this unambiguous mode the default without a\n> > breaking change.\n>\n> Yup, if the old versions misinterpret exactly the same way as\n> before, then it does not even have to be called \"unambiguous mode\"\n> that is on by default.  I doubt it is possible, though.\n>\n\nHmm. If we add a new unambiguous marker after the ---, old versions\nwould see '...' and know to cut the description. New versions would\nwait for <NEW MARKER> and properly ignore any diff/etc prior to this.\n\nSince <NEW MARKER> is after a ---, it would be ignored and not\ninserted as part of the commit message, and because all versions\nuniversally accept cruft between --- and the diff start, this should\nbe acceptable right?\n"},{"id":"535731","messageId":"CA+P7+xpYSyhBoC23RLycVXFSBB2=dgsQrnvLkk0D7afOqWyafA@mail.gmail.com","threadId":"64933","inReplyTo":"CA+P7+xo0-9h_V8xGQaEdgBEaxjrbrNOdPfmFmhKup+Z-7w0zUw@mail.gmail.com","subject":"Re: git-am applies commit message diffs","fromName":"Jacob Keller","fromEmail":"jacob.keller@gmail.com","sentAt":"2026-02-11T02:34:05Z","receivedAt":"2026-02-11T02:34:16Z","isPatch":false,"sender":{"key":"jacob.keller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"On Tue, Feb 10, 2026 at 6:31 PM Jacob Keller <jacob.keller@gmail.com> wrote:\n>\n> On Tue, Feb 10, 2026 at 7:47 AM Junio C Hamano <gitster@pobox.com> wrote:\n> >\n> > Patrick Steinhardt <ps@pks.im> writes:\n> >\n> > > That is worth a thought indeed. I guess one of the biggest questions\n> > > here is whether we can introduce such an unambiguous mode in such a way\n> > > that old Git clients/patch(1) would continue to understand them. I\n> > > wouldn't mind much if they would still misinterpret the ambiguous parts.\n> > > But if so, we could make this unambiguous mode the default without a\n> > > breaking change.\n> >\n> > Yup, if the old versions misinterpret exactly the same way as\n> > before, then it does not even have to be called \"unambiguous mode\"\n> > that is on by default.  I doubt it is possible, though.\n> >\n>\n> Hmm. If we add a new unambiguous marker after the ---, old versions\n> would see '...' and know to cut the description. New versions would\n> wait for <NEW MARKER> and properly ignore any diff/etc prior to this.\n>\n> Since <NEW MARKER> is after a ---, it would be ignored and not\n> inserted as part of the commit message, and because all versions\n> universally accept cruft between --- and the diff start, this should\n> be acceptable right?\n\nKeeping in mind we'd have to use <NEW MARKER> as something that we\nsomehow reject as being a valid part of a commit message somehow, so\nthat you can't accidentally insert it, and we'd need to be careful\nabout rejecting formatting such a patch, and probably complaining on\nthe receiving end if we see multiple markers.. Trickier than it sounds\nI imagine.\n"},{"id":"535738","messageId":"20260211074751.GB1867915@coredump.intra.peff.net","threadId":"64933","inReplyTo":"CA+P7+xpYSyhBoC23RLycVXFSBB2=dgsQrnvLkk0D7afOqWyafA@mail.gmail.com","subject":"Re: git-am applies commit message diffs","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-11T07:47:51Z","receivedAt":"2026-02-11T07:47:53Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Feb 10, 2026 at 06:34:05PM -0800, Jacob Keller wrote:\n\n> > Hmm. If we add a new unambiguous marker after the ---, old versions\n> > would see '...' and know to cut the description. New versions would\n> > wait for <NEW MARKER> and properly ignore any diff/etc prior to this.\n> >\n> > Since <NEW MARKER> is after a ---, it would be ignored and not\n> > inserted as part of the commit message, and because all versions\n> > universally accept cruft between --- and the diff start, this should\n> > be acceptable right?\n> \n> Keeping in mind we'd have to use <NEW MARKER> as something that we\n> somehow reject as being a valid part of a commit message somehow, so\n> that you can't accidentally insert it, and we'd need to be careful\n> about rejecting formatting such a patch, and probably complaining on\n> the receiving end if we see multiple markers.. Trickier than it sounds\n> I imagine.\n\nYeah, on reading your first message, I wondered if we would run into a\ncommit message adding \"---\" followed by the new marker. If the new\nmarker is forbidden, I guess that works. But how ugly is that new marker\ngoing to be, then? ;) We'll now see it in every email.\n\nIf we are going to modify what format-patch produces, I'd be more\ninclined to have it perform some reversible quoting on the commit\nmessage so that \"---\" and \"diff\" lines are not recognized. And then that\nquoting only has to kick in when a message would be ambiguous, so most\npeople wouldn't even see it.\n\nIf an older version of git-am (that does not understand how to unquote\nit) receives the mail, the worst case is you'd see the quoting in the\nresulting commit message. So if we make it not-too-ugly, that may not be\nso bad. Think something along the lines of seeing \">From\" in emails. It\nis gross and ugly, but you can still read the email.\n\n\nAll that said, if the main goal is just avoiding accidental diffs in\ncommit messages (and not worrying about truncation due to \"---\" in\nmessages), there may be a simpler receiver-side solution. If the\nreceiver expects the message to be generated by Git, then it will expect\nthere to be a \"---\" line. And we will not expect any diff before then.\nSo could we just have a \"git am --strict\" mode (and perhaps matching\nconfig option) that always looks for the \"---\" separator?\n\nIt's not foolproof, but I suspect it would help with the worst cases of\nembedded diffs. And it's not that hard to implement.\n\n-Peff\n"},{"id":"535775","messageId":"958c4cb1-8ca0-4559-abfc-b50d009cc680@app.fastmail.com","threadId":"64933","inReplyTo":"20260211074751.GB1867915@coredump.intra.peff.net","subject":"Re: git-am applies commit message diffs","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-11T15:23:02Z","receivedAt":"2026-02-11T15:23:23Z","isPatch":false,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Wed, Feb 11, 2026, at 08:47, Jeff King wrote:\n> On Tue, Feb 10, 2026 at 06:34:05PM -0800, Jacob Keller wrote:\n>\n>> > Hmm. If we add a new unambiguous marker after the ---, old versions\n>> > would see '...' and know to cut the description. New versions would\n>> > wait for <NEW MARKER> and properly ignore any diff/etc prior to this.\n>> >\n>> > Since <NEW MARKER> is after a ---, it would be ignored and not\n>> > inserted as part of the commit message, and because all versions\n>> > universally accept cruft between --- and the diff start, this should\n>> > be acceptable right?\n>>\n>> Keeping in mind we'd have to use <NEW MARKER> as something that we\n>> somehow reject as being a valid part of a commit message somehow, so\n>> that you can't accidentally insert it, and we'd need to be careful\n>> about rejecting formatting such a patch, and probably complaining on\n>> the receiving end if we see multiple markers.. Trickier than it sounds\n>> I imagine.\n>\n> Yeah, on reading your first message, I wondered if we would run into a\n> commit message adding \"---\" followed by the new marker. If the new\n> marker is forbidden, I guess that works. But how ugly is that new marker\n> going to be, then? ;) We'll now see it in every email.\n\nMaybe it could be something like `<symbols><space>`? It’s difficult to accidentally \nget a trailing whitespace into a commit.\n\n> If we are going to modify what format-patch produces, I'd be more\n> inclined to have it perform some reversible quoting on the commit\n> message so that \"---\" and \"diff\" lines are not recognized. And then that\n> quoting only has to kick in when a message would be ambiguous, so most\n> people wouldn't even see it.\n\nThis sounds better anyway.\n\n>[snip]\n"},{"id":"535780","messageId":"xmqqa4xfwadc.fsf@gitster.g","threadId":"64933","inReplyTo":"20260211074751.GB1867915@coredump.intra.peff.net","subject":"Re: git-am applies commit message diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-11T15:47:11Z","receivedAt":"2026-02-11T15:47:14Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> All that said, if the main goal is just avoiding accidental diffs in\n> commit messages (and not worrying about truncation due to \"---\" in\n> messages), there may be a simpler receiver-side solution. If the\n> receiver expects the message to be generated by Git, then it will expect\n> there to be a \"---\" line. And we will not expect any diff before then.\n> So could we just have a \"git am --strict\" mode (and perhaps matching\n> config option) that always looks for the \"---\" separator?\n>\n> It's not foolproof, but I suspect it would help with the worst cases of\n> embedded diffs. And it's not that hard to implement.\n\nYup, if the payload is known to be generated by \"git\", which is much\nmore likely these days than back when \"git am\" (or \"git applymbox\")\nwas written, can ignore \"Index:\" and \"diff -\" when deciding when the\nlog message part of a piece of e-mail ends.  I like that approach.\n\n"},{"id":"535896","messageId":"V3_format-patch_caveats.354@msgid.xyz","threadId":"64933","inReplyTo":"V2_format-patch_caveats.34b@msgid.xyz","subject":"[PATCH v3] doc: add caveat about round-tripping format-patch","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-12T22:28:23Z","receivedAt":"2026-02-12T22:28:54Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\ngit-format-patch(1) and git-am(1) deal with formatting commits as\npatches and applying them, respectively. Naturally they use a few\ndelimiters to mark where the commit message ends. This can lead to\nsurprising behavior when these delimiters are used in the commit\nmessage itself.\n\ngit-format-patch(1) will accept any commit message and not warn or error\nabout these delimiters being used.[1]\n\nEspecially problematic is the presence of unindented diffs in the commit\nmessage; the patch machinery will naturally (since the commit message\nhas ended) try to apply that diff and everything after it.[2]\n\nIt is unclear whether any commands in this chain will learn to warn\nabout this. One concern could be that users have learned to rely on\nthe three-dash line rule to conveniently add extra-commit message\ninformation in the commit message, knowing that git-am(1) will\nignore it.[4]\n\nAll of this is covered already, technically. However, we should spell\nout the implications.\n\n† 1: There is also git-commit(1) to consider. However, making that\n     command warn or error out over such delimiters would be disruptive\n     to all Git users who never use email in their workflow.\n† 2: Recently patch(1) caused this issue for a project, but it was noted\n     that git-am(1) has the same behavior[3]\n† 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n† 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n     https://lore.kernel.org/git/V3_format-patch_caveats.354@msgid.xyz/\n\nReported-by: Matthias Beyer <mail@beyermatthias.de>\nReported-by: Christoph Anton Mitterer <calestyo@scientia.org>\nReported-by: Matheus Tavares <matheus.tavb@gmail.com>\nReported-by: Chris Packham <judge.packham@gmail.com>\nHelped-by: Jakob Haufe <sur5r@sur5r.net>\nHelped-by: Phillip Wood <phillip.wood@dunelm.org.uk>\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\n---\n\nv3:\n\nDrop “[GitHub] Markdown” based on discussion with Phillip.\n\nAddress Junio’s feedback about not using a needless\n“this means” construct.\n\nAlso:\n• Pull out the whole syntactic rules section instead of just the list\n• Add back the solution paragraph (indent diff or other problematic\n  text) that I accidentally deleted in v2.\n• Resolve the thematic break problem (not rendered in man) by using a\n  subheading (Patch Application)\n• Fine, Merriam Webster says that roundtripping is “less commonly\n  used” (use round-trip)\n\nLink to v2: https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\nLink to v1: https://lore.kernel.org/git/format-patch_caveats.281@msgid.xyz/\n---\n Documentation/format-patch-caveats.adoc       | 33 +++++++++++++++++++\n .../format-patch-end-of-commit-message.adoc   |  8 +++++\n Documentation/git-am.adoc                     | 19 +++++++----\n Documentation/git-format-patch.adoc           |  4 +++\n Documentation/git-send-email.adoc             |  5 +++\n 5 files changed, 62 insertions(+), 7 deletions(-)\n create mode 100644 Documentation/format-patch-caveats.adoc\n create mode 100644 Documentation/format-patch-end-of-commit-message.adoc\n\ndiff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\nnew file mode 100644\nindex 00000000000..807a65b885b\n--- /dev/null\n+++ b/Documentation/format-patch-caveats.adoc\n@@ -0,0 +1,33 @@\n+The output from linkgit:git-format-patch[1] can lead to a different\n+commit message when applied with linkgit:git-am[1]. The patch that is\n+applied may also be different from the one that was generated, or patch\n+application may fail outright.\n+ifdef::git-am[]\n+See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n+endif::git-am[]\n+\n+ifndef::git-am[]\n+include::format-patch-end-of-commit-message.adoc[]\n+endif::git-am[]\n+\n+Note that this is especially problematic for unindented diffs that occur\n+in the commit message; the diff in the commit message might get applied\n+along with the patch section, or the patch application machinery might\n+trip up because the patch target doesn't apply. This could for example\n+be caused by a diff in a Markdown code block.\n+\n+The solution for this is to indent the diff or other text that could\n+cause problems.\n+\n+This loss of fidelity might be simple to notice if you are applying\n+patches directly from a mailbox. However, changes originating from Git\n+could be applied in bulk, in which case this would be much harder to\n+notice. This could for example be a Linux distribution which uses patch\n+files to apply changes on top of the commits from the upstream\n+repositories. This goes to show that this behavior does not only impact\n+email workflows.\n+\n+Given these limitations, one might be tempted to use a general-purpose\n+utility like patch(1) instead. However, patch(1) will not only look for\n+unindented diffs (like linkgit:git-am[1]) but will try to apply indented\n+diffs as well.\ndiff --git a/Documentation/format-patch-end-of-commit-message.adoc b/Documentation/format-patch-end-of-commit-message.adoc\nnew file mode 100644\nindex 00000000000..ec1ef79f5e3\n--- /dev/null\n+++ b/Documentation/format-patch-end-of-commit-message.adoc\n@@ -0,0 +1,8 @@\n+Any line that is of the form:\n+\n+* three-dashes and end-of-line, or\n+* a line that begins with \"diff -\", or\n+* a line that begins with \"Index: \"\n+\n+is taken as the beginning of a patch, and the commit log message\n+is terminated before the first occurrence of such a line.\ndiff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\nindex 0c94776e296..972398d4575 100644\n--- a/Documentation/git-am.adoc\n+++ b/Documentation/git-am.adoc\n@@ -231,10 +231,11 @@ applying.\n --allow-empty::\n \tAfter a patch failure on an input e-mail message lacking a patch,\n \tcreate an empty commit with the contents of the e-mail message\n \tas its log message.\n \n+[[discussion]]\n DISCUSSION\n ----------\n \n The commit author name is taken from the \"From: \" line of the\n message, and commit author date is taken from the \"Date: \" line\n@@ -250,18 +251,15 @@ The commit message is formed by the title taken from the\n \"Subject: \", a blank line and the body of the message up to\n where the patch begins.  Excess whitespace at the end of each\n line is automatically stripped.\n \n The patch is expected to be inline, directly following the\n-message.  Any line that is of the form:\n+message.\n+include::format-patch-end-of-commit-message.adoc[]\n \n-* three-dashes and end-of-line, or\n-* a line that begins with \"diff -\", or\n-* a line that begins with \"Index: \"\n-\n-is taken as the beginning of a patch, and the commit log message\n-is terminated before the first occurrence of such a line.\n+This means that the contents of the commit message can inadvertently\n+interrupt the processing (see the <<caveats,CAVEATS>> section below).\n \n When initially invoking `git am`, you give it the names of the mailboxes\n to process.  Upon seeing the first patch that does not apply, it\n aborts in the middle.  You can recover from this in one of two ways:\n \n@@ -281,10 +279,17 @@ Before any patches are applied, ORIG_HEAD is set to the tip of the\n current branch.  This is useful if you have problems with multiple\n commits, like running 'git am' on the wrong branch or an error in the\n commits that is more easily fixed by changing the mailbox (e.g.\n errors in the \"From:\" lines).\n \n+[[caveats]]\n+CAVEATS\n+-------\n+\n+:git-am: 1\n+include::format-patch-caveats.adoc[]\n+\n HOOKS\n -----\n This command can run `applypatch-msg`, `pre-applypatch`,\n and `post-applypatch` hooks.  See linkgit:githooks[5] for more\n information.\ndiff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\nindex 9a7807ca71a..bac9b818f3b 100644\n--- a/Documentation/git-format-patch.adoc\n+++ b/Documentation/git-format-patch.adoc\n@@ -796,10 +796,14 @@ CAVEATS\n Note that `format-patch` will omit merge commits from the output, even\n if they are part of the requested range. A simple \"patch\" does not\n include enough information for the receiving end to reproduce the same\n merge commit.\n \n+=== PATCH APPLICATION\n+\n+include::format-patch-caveats.adoc[]\n+\n SEE ALSO\n --------\n linkgit:git-am[1], linkgit:git-send-email[1]\n \n GIT\ndiff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc\nindex ebe8853e9f5..0b118df6498 100644\n--- a/Documentation/git-send-email.adoc\n+++ b/Documentation/git-send-email.adoc\n@@ -690,10 +690,15 @@ Links of a few such community maintained helpers are:\n \t  (cross platform client that can send emails using the ProtonMail API)\n \n \t- https://github.com/AdityaGarg8/git-credential-email[git-msgraph]\n \t  (cross platform client that can send emails using the Microsoft Graph API)\n \n+CAVEATS\n+-------\n+\n+include::format-patch-caveats.adoc[]\n+\n SEE ALSO\n --------\n linkgit:git-format-patch[1], linkgit:git-imap-send[1], mbox(5)\n \n GIT\n\nInterdiff against v2:\n  diff --git a/Documentation/format-patch-caveats.adoc b/Documentation/format-patch-caveats.adoc\n  index c666d709742..807a65b885b 100644\n  --- a/Documentation/format-patch-caveats.adoc\n  +++ b/Documentation/format-patch-caveats.adoc\n  @@ -1,28 +1,25 @@\n  -Patches produced by linkgit:git-format-patch[1] are inline. This means\n  -that the output from that command can lead to a different commit message\n  -when applied with linkgit:git-am[1]. It can also mean that the patch\n  -that is applied is not the same as the one that was generated, or that\n  -the patch application fails outright.\n  +The output from linkgit:git-format-patch[1] can lead to a different\n  +commit message when applied with linkgit:git-am[1]. The patch that is\n  +applied may also be different from the one that was generated, or patch\n  +application may fail outright.\n   ifdef::git-am[]\n   See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n   endif::git-am[]\n   \n   ifndef::git-am[]\n  -Any line that is of the form:\n  -\n   include::format-patch-end-of-commit-message.adoc[]\n  -\n  -will terminate the commit message and cause the patch machinery to start\n  -searching for patches to apply.\n   endif::git-am[]\n   \n   Note that this is especially problematic for unindented diffs that occur\n   in the commit message; the diff in the commit message might get applied\n   along with the patch section, or the patch application machinery might\n   trip up because the patch target doesn't apply. This could for example\n  -be caused by a diff in a GitHub Markdown code block.\n  +be caused by a diff in a Markdown code block.\n  +\n  +The solution for this is to indent the diff or other text that could\n  +cause problems.\n   \n   This loss of fidelity might be simple to notice if you are applying\n   patches directly from a mailbox. However, changes originating from Git\n   could be applied in bulk, in which case this would be much harder to\n   notice. This could for example be a Linux distribution which uses patch\n  diff --git a/Documentation/format-patch-end-of-commit-message.adoc b/Documentation/format-patch-end-of-commit-message.adoc\n  index 47399ae7266..ec1ef79f5e3 100644\n  --- a/Documentation/format-patch-end-of-commit-message.adoc\n  +++ b/Documentation/format-patch-end-of-commit-message.adoc\n  @@ -1,3 +1,8 @@\n  +Any line that is of the form:\n  +\n   * three-dashes and end-of-line, or\n   * a line that begins with \"diff -\", or\n   * a line that begins with \"Index: \"\n  +\n  +is taken as the beginning of a patch, and the commit log message\n  +is terminated before the first occurrence of such a line.\n  diff --git a/Documentation/git-am.adoc b/Documentation/git-am.adoc\n  index 756dfd722b9..972398d4575 100644\n  --- a/Documentation/git-am.adoc\n  +++ b/Documentation/git-am.adoc\n  @@ -251,17 +251,13 @@ The commit message is formed by the title taken from the\n   \"Subject: \", a blank line and the body of the message up to\n   where the patch begins.  Excess whitespace at the end of each\n   line is automatically stripped.\n   \n   The patch is expected to be inline, directly following the\n  -message.  Any line that is of the form:\n  -\n  +message.\n   include::format-patch-end-of-commit-message.adoc[]\n   \n  -is taken as the beginning of a patch, and the commit log message\n  -is terminated before the first occurrence of such a line.\n  -\n   This means that the contents of the commit message can inadvertently\n   interrupt the processing (see the <<caveats,CAVEATS>> section below).\n   \n   When initially invoking `git am`, you give it the names of the mailboxes\n   to process.  Upon seeing the first patch that does not apply, it\n  diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc\n  index 36851aaf5e1..bac9b818f3b 100644\n  --- a/Documentation/git-format-patch.adoc\n  +++ b/Documentation/git-format-patch.adoc\n  @@ -796,11 +796,11 @@ CAVEATS\n   Note that `format-patch` will omit merge commits from the output, even\n   if they are part of the requested range. A simple \"patch\" does not\n   include enough information for the receiving end to reproduce the same\n   merge commit.\n   \n  -'''\n  +=== PATCH APPLICATION\n   \n   include::format-patch-caveats.adoc[]\n   \n   SEE ALSO\n   --------\n\nRange-diff against v2:\n1:  c54f394bb33 ! 1:  b51273c82c9 doc: add caveat about roundtripping format-patch\n    @@ Metadata\n     Author: Kristoffer Haugsbakk <code@khaugsbakk.name>\n     \n      ## Commit message ##\n    -    doc: add caveat about roundtripping format-patch\n    +    doc: add caveat about round-tripping format-patch\n     \n         git-format-patch(1) and git-am(1) deal with formatting commits as\n         patches and applying them, respectively. Naturally they use a few\n    @@ Commit message\n              that git-am(1) has the same behavior[3]\n         † 3: https://github.com/i3/i3/pull/6564#issuecomment-3858381425\n         † 4: https://lore.kernel.org/git/xmqqldh4b5y2.fsf@gitster.g/\n    -         https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\n    +         https://lore.kernel.org/git/V3_format-patch_caveats.354@msgid.xyz/\n     \n         Reported-by: Matthias Beyer <mail@beyermatthias.de>\n         Reported-by: Christoph Anton Mitterer <calestyo@scientia.org>\n         Reported-by: Matheus Tavares <matheus.tavb@gmail.com>\n         Reported-by: Chris Packham <judge.packham@gmail.com>\n         Helped-by: Jakob Haufe <sur5r@sur5r.net>\n    +    Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n     \n         ---\n     \n    -    v2:\n    +    v3:\n     \n    -    Address feedback from Phillip Wood.\n    +    Drop “[GitHub] Markdown” based on discussion with Phillip.\n     \n    -    Cc: Phillip Wood <phillip.wood@dunelm.org.uk>\n    +    Address Junio’s feedback about not using a needless\n    +    “this means” construct.\n     \n    -    • Drop the code blocks with the diffs; the prose speaks for itself, no need\n    -      to take up space\n    -    • Don’t discuss git-send-email(1). We already know that git-format-patch(1)\n    -      is the generator. It is mentioned in git-send-email(1).\n    -    • Try to be more clear about the case where someone might be applying a\n    -      diff. Use the example from Matthias Beyer in:\n    +    Also:\n    +    • Pull out the whole syntactic rules section instead of just the list\n    +    • Add back the solution paragraph (indent diff or other problematic\n    +      text) that I accidentally deleted in v2.\n    +    • Resolve the thematic break problem (not rendered in man) by using a\n    +      subheading (Patch Application)\n    +    • Fine, Merriam Webster says that roundtripping is “less commonly\n    +      used” (use round-trip)\n     \n    -          https://lore.kernel.org/git/gfxpnecn2cdtmeiape2d4x5aybuyyqi4c7m6te3khgct34dd44@wqusigna2nsp/\n    -\n    -      Hopefully I explained it correctly?\n    -    • Add a “this goes to show...”... which seems to emphasize the point\n    -      without being redundant. Hopefully.\n    -\n    -    Try to address feedback from Junio C Hamano by adding more nuance: the diff\n    -    in the commit message might be applied as well, or the patch machinery\n    -    might trip on something and fail.\n    -\n    -    Finally, in the middle of discussing the three possible cmt. message\n    -    delimiters, I noticed that the three points were drifting apart. So I\n    -    decided to use the list already used in git-am(1) and be done with it in\n    -    one place.\n    -\n    -    ---\n    -\n    -    It seems that the section break in git-format-patch(1) does not get\n    -    applied in the man output (according to `Documentation/doc-diff`\n    -    apparently)? Maybe this is the wrong construct? I couldn’t find any\n    -    other thematic breaks here (though there are several variations).\n    +    Link to v2: https://lore.kernel.org/git/V2_format-patch_caveats.34b@msgid.xyz/\n    +    Link to v1: https://lore.kernel.org/git/format-patch_caveats.281@msgid.xyz/\n     \n      ## Documentation/format-patch-caveats.adoc (new) ##\n     @@\n    -+Patches produced by linkgit:git-format-patch[1] are inline. This means\n    -+that the output from that command can lead to a different commit message\n    -+when applied with linkgit:git-am[1]. It can also mean that the patch\n    -+that is applied is not the same as the one that was generated, or that\n    -+the patch application fails outright.\n    ++The output from linkgit:git-format-patch[1] can lead to a different\n    ++commit message when applied with linkgit:git-am[1]. The patch that is\n    ++applied may also be different from the one that was generated, or patch\n    ++application may fail outright.\n     +ifdef::git-am[]\n     +See the <<discussion,DISCUSSION>> section above for the syntactic rules.\n     +endif::git-am[]\n     +\n     +ifndef::git-am[]\n    -+Any line that is of the form:\n    -+\n     +include::format-patch-end-of-commit-message.adoc[]\n    -+\n    -+will terminate the commit message and cause the patch machinery to start\n    -+searching for patches to apply.\n     +endif::git-am[]\n     +\n     +Note that this is especially problematic for unindented diffs that occur\n     +in the commit message; the diff in the commit message might get applied\n     +along with the patch section, or the patch application machinery might\n     +trip up because the patch target doesn't apply. This could for example\n    -+be caused by a diff in a GitHub Markdown code block.\n    ++be caused by a diff in a Markdown code block.\n    ++\n    ++The solution for this is to indent the diff or other text that could\n    ++cause problems.\n     +\n     +This loss of fidelity might be simple to notice if you are applying\n     +patches directly from a mailbox. However, changes originating from Git\n    @@ Documentation/format-patch-caveats.adoc (new)\n     \n      ## Documentation/format-patch-end-of-commit-message.adoc (new) ##\n     @@\n    ++Any line that is of the form:\n    ++\n     +* three-dashes and end-of-line, or\n     +* a line that begins with \"diff -\", or\n     +* a line that begins with \"Index: \"\n    ++\n    ++is taken as the beginning of a patch, and the commit log message\n    ++is terminated before the first occurrence of such a line.\n     \n      ## Documentation/git-am.adoc ##\n     @@ Documentation/git-am.adoc: applying.\n    @@ Documentation/git-am.adoc: applying.\n      DISCUSSION\n      ----------\n      \n    -@@ Documentation/git-am.adoc: line is automatically stripped.\n    +@@ Documentation/git-am.adoc: where the patch begins.  Excess whitespace at the end of each\n    + line is automatically stripped.\n    + \n      The patch is expected to be inline, directly following the\n    - message.  Any line that is of the form:\n    +-message.  Any line that is of the form:\n    ++message.\n    ++include::format-patch-end-of-commit-message.adoc[]\n      \n     -* three-dashes and end-of-line, or\n     -* a line that begins with \"diff -\", or\n     -* a line that begins with \"Index: \"\n    -+include::format-patch-end-of-commit-message.adoc[]\n    - \n    - is taken as the beginning of a patch, and the commit log message\n    - is terminated before the first occurrence of such a line.\n    - \n    +-\n    +-is taken as the beginning of a patch, and the commit log message\n    +-is terminated before the first occurrence of such a line.\n     +This means that the contents of the commit message can inadvertently\n     +interrupt the processing (see the <<caveats,CAVEATS>> section below).\n    -+\n    + \n      When initially invoking `git am`, you give it the names of the mailboxes\n      to process.  Upon seeing the first patch that does not apply, it\n    - aborts in the middle.  You can recover from this in one of two ways:\n     @@ Documentation/git-am.adoc: commits, like running 'git am' on the wrong branch or an error in the\n      commits that is more easily fixed by changing the mailbox (e.g.\n      errors in the \"From:\" lines).\n    @@ Documentation/git-format-patch.adoc: if they are part of the requested range. A\n      include enough information for the receiving end to reproduce the same\n      merge commit.\n      \n    -+'''\n    ++=== PATCH APPLICATION\n     +\n     +include::format-patch-caveats.adoc[]\n     +\n\nbase-commit: 3e0db84c88c57e70ac8be8c196dfa92c5d656fbc\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535901","messageId":"xmqqtsvllfdc.fsf@gitster.g","threadId":"64933","inReplyTo":"V3_format-patch_caveats.354@msgid.xyz","subject":"Re: [PATCH v3] doc: add caveat about round-tripping format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-12T23:19:11Z","receivedAt":"2026-02-12T23:19:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"kristofferhaugsbakk@fastmail.com writes:\n\n> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> ...\n> All of this is covered already, technically. However, we should spell\n> out the implications.\n\nI've read the new text (without formatting, I have to admit) again,\nand did not see anything questionable.  Nicely written.\n\nShall we mark this for 'next'?\n\nThanks.\n"},{"id":"535930","messageId":"cover.1770993281.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"20260206090358.GA2761602@coredump.intra.peff.net","subject":"[PATCH v2 0/2] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-13T14:34:47Z","receivedAt":"2026-02-13T14:35:06Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThis series adds a check to the sample commit-msg hook to reject commit\nmessages where the body of the message contains lines starting with\n\"diff -\" and \"Index: \". Such lines confuse \"git am\".\n\nChanges since V1:\n\n - Allow subjects to start with \"diff -\" as they end up in an email\n   header and so do not confuse \"git am\"\n\n - Allow \"---\" lines as they are useful when preparing patches.\n\nBase-Commit: b2826b52eb7caff9f4ed6e85ec45e338bf02ad09\nPublished-As: https://github.com/phillipwood/git/releases/tag/pw%2Fsample-commit-msg-reject-diff%2Fv2\nView-Changes-At: https://github.com/phillipwood/git/compare/b2826b52e...494f4df68\nFetch-It-Via: git fetch https://github.com/phillipwood/git pw/sample-commit-msg-reject-diff/v2\n\n\nPhillip Wood (2):\n  templates: add .gitattributes entry for sample hooks\n  templates: detect commit messages containing diffs\n\n .editorconfig                     |  2 +-\n .gitattributes                    |  1 +\n templates/hooks/commit-msg.sample | 54 +++++++++++++++++++++++++++++--\n 3 files changed, 54 insertions(+), 3 deletions(-)\n\nRange-diff against v1:\n1:  5f5e3091435 = 1:  5f5e3091435 templates: add .gitattributes entry for sample hooks\n2:  e75978b9591 ! 2:  494f4df6865 templates: detect commit messages containing diffs\n    @@ Metadata\n      ## Commit message ##\n         templates: detect commit messages containing diffs\n     \n    -    If a commit message contains a diff that is not indented then \"git\n    -    am\" will treat that diff as part of the patch rather than as part\n    -    of the commit message. This allows it to apply email messages that\n    -    were created by adding a commit message in front of a regular diff\n    +    If the body of a commit message contains a diff that is not indented\n    +    then \"git am\" will treat that diff as part of the patch rather than\n    +    as part of the commit message. This allows it to apply email messages\n    +    that were created by adding a commit message in front of a regular diff\n         without adding the \"---\" separator used by \"git format-patch\". This\n         often surprises users [1-4] so add a check to the sample \"commit-msg\"\n    -    hook to reject messages that would confuse \"git am\".\n    -\n    -    Detecting if the message contains a diff is complicated by the hook\n    -    being passed the message before it is cleaned up so we need to ignore\n    -    any diffs below the scissors line. There are also two possible\n    -    config keys to check to find the comment character at the start\n    -    of the scissors line.\n    +    hook to reject messages that would confuse \"git am\". Even if a project\n    +    does not use an email based workflow it is not uncommon for people\n    +    to generate patches from it and apply them with \"git am\". Therefore\n    +    it is still worth discouraging the creation of commit messages that\n    +    would not be applied correctly.\n    +\n    +    A further source of confusion when applying patches with \"git am\" is\n    +    the \"---\" separator that is added by \"git format patch\". If a commit\n    +    message body contains that line then it will be truncated by \"git am\".\n    +    As this is often used by patch authors to add some commentary that\n    +    they do not want to end up in the commit message when the patch is\n    +    applied, the hook does not complain about the presence of \"---\" lines\n    +    in the message.\n    +\n    +    Detecting if the message contains a diff is complicated by the\n    +    hook being passed the message before it is cleaned up so we need to\n    +    ignore any diffs below the scissors line. There are also two possible\n    +    config keys to check to find the comment character at the start of\n    +    the scissors line. The first paragraph of the commit message becomes\n    +    the email subject header which beings \"Subject: \" and so does not\n    +    need to be checked. The trailing \".*\" when matching commented lines\n    +    ensures that if the comment string ends with a \"$\" it is not treated\n    +    as an anchor.\n     \n         [1] https://lore.kernel.org/git/bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm\n         [2] https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n    @@ templates/hooks/commit-msg.sample\n     +\t\t\tp\n     +\t\t}'\n     +)\"\n    -+line=\"$(sed -n -e \"/^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$/q\n    -+\t\t   /^diff -/{p;q;}\n    -+\t\t   /^Index: /{p;q;}\" \"$1\")\"\n    ++scissors_line=\"^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$\"\n    ++comment_line=\"^${comment_re}.*\"\n    ++blank_line='^[ \t]*$'\n    ++# Disallow lines starting with \"diff -\" or \"Index: \" in the body of the\n    ++# message. Stop looking if we see a scissors line.\n    ++line=\"$(sed -n -e \"\n    ++\t# Skip comments and blank lines at the start of the file.\n    ++\t/${scissors_line}/q\n    ++\t/${comment_line}/d\n    ++\t/${blank_line}/d\n    ++\t# The first paragraph will become the subject header so\n    ++\t# does not need to be checked.\n    ++\t: subject\n    ++\tn\n    ++\t/${scissors_line}/q\n    ++\t/${blank_line}/!b subject\n    ++\t# Check the body of the message for problematic\n    ++\t# prefixes.\n    ++\t: body\n    ++\tn\n    ++\t/${scissors_line}/q\n    ++\t/${comment_line}/b body\n    ++\t/^diff -/{p;q;}\n    ++\t/^Index: /{p;q;}\n    ++\tb body\n    ++\t\" \"$1\")\"\n     +if test -n \"$line\"\n     +then\n     +\techo >&2 \"Message contains a diff that will confuse 'git am'.\"\n3:  83c100a73ec < -:  ----------- templates: detect messages that contain a separator line\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535931","messageId":"5f5e30914355ba108d8f4ce9157369e979f585e4.1770993281.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"cover.1770993281.git.phillip.wood@dunelm.org.uk","subject":"[PATCH v2 1/2] templates: add .gitattributes entry for sample hooks","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-13T14:34:48Z","receivedAt":"2026-02-13T14:35:06Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThe sample hooks are shell scripts but the filenames end with \".sample\"\nso they need their own .gitattributes rule. Update our editorconfig\nsettings to match the attributes as well.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n .editorconfig  | 2 +-\n .gitattributes | 1 +\n 2 files changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/.editorconfig b/.editorconfig\nindex 2d3929b5916..6e4eaa8e955 100644\n--- a/.editorconfig\n+++ b/.editorconfig\n@@ -4,7 +4,7 @@ insert_final_newline = true\n \n # The settings for C (*.c and *.h) files are mirrored in .clang-format.  Keep\n # them in sync.\n-[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile}]\n+[{*.{c,h,sh,bash,perl,pl,pm,txt,adoc},config.mak.*,Makefile,templates/hooks/*.sample}]\n indent_style = tab\n tab_width = 8\n \ndiff --git a/.gitattributes b/.gitattributes\nindex 38b1c52fe0e..556322be01b 100644\n--- a/.gitattributes\n+++ b/.gitattributes\n@@ -18,3 +18,4 @@ CODE_OF_CONDUCT.md -whitespace\n /Documentation/user-manual.adoc conflict-marker-size=32\n /t/t????-*.sh conflict-marker-size=32\n /t/unit-tests/clar/test/expected/* whitespace=-blank-at-eof\n+/templates/hooks/*.sample whitespace=indent,trail,space,incomplete text eol=lf\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535932","messageId":"494f4df6865f81eba42584ead81327c9a305d0d4.1770993281.git.phillip.wood@dunelm.org.uk","threadId":"64933","inReplyTo":"cover.1770993281.git.phillip.wood@dunelm.org.uk","subject":"[PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-13T14:34:49Z","receivedAt":"2026-02-13T14:35:07Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nIf the body of a commit message contains a diff that is not indented\nthen \"git am\" will treat that diff as part of the patch rather than\nas part of the commit message. This allows it to apply email messages\nthat were created by adding a commit message in front of a regular diff\nwithout adding the \"---\" separator used by \"git format-patch\". This\noften surprises users [1-4] so add a check to the sample \"commit-msg\"\nhook to reject messages that would confuse \"git am\". Even if a project\ndoes not use an email based workflow it is not uncommon for people\nto generate patches from it and apply them with \"git am\". Therefore\nit is still worth discouraging the creation of commit messages that\nwould not be applied correctly.\n\nA further source of confusion when applying patches with \"git am\" is\nthe \"---\" separator that is added by \"git format patch\". If a commit\nmessage body contains that line then it will be truncated by \"git am\".\nAs this is often used by patch authors to add some commentary that\nthey do not want to end up in the commit message when the patch is\napplied, the hook does not complain about the presence of \"---\" lines\nin the message.\n\nDetecting if the message contains a diff is complicated by the\nhook being passed the message before it is cleaned up so we need to\nignore any diffs below the scissors line. There are also two possible\nconfig keys to check to find the comment character at the start of\nthe scissors line. The first paragraph of the commit message becomes\nthe email subject header which beings \"Subject: \" and so does not\nneed to be checked. The trailing \".*\" when matching commented lines\nensures that if the comment string ends with a \"$\" it is not treated\nas an anchor.\n\n[1] https://lore.kernel.org/git/bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm\n[2] https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n[3] https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n[4] https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n templates/hooks/commit-msg.sample | 54 +++++++++++++++++++++++++++++--\n 1 file changed, 52 insertions(+), 2 deletions(-)\n\ndiff --git a/templates/hooks/commit-msg.sample b/templates/hooks/commit-msg.sample\nindex b58d1184a9d..f7458efe62f 100755\n--- a/templates/hooks/commit-msg.sample\n+++ b/templates/hooks/commit-msg.sample\n@@ -15,10 +15,60 @@\n # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n # grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n \n-# This example catches duplicate Signed-off-by lines.\n+# This example catches duplicate Signed-off-by lines and messages that\n+# would confuse 'git am'.\n+\n+ret=0\n \n test \"\" = \"$(grep '^Signed-off-by: ' \"$1\" |\n \t sort | uniq -c | sed -e '/^[ \t]*1[ \t]/d')\" || {\n \techo >&2 Duplicate Signed-off-by lines.\n-\texit 1\n+\tret=1\n }\n+\n+comment_re=\"$(\n+\t{\n+\t\tgit config --get-regexp \"^core\\.comment(char|string)\\$\" ||\n+\t\t\techo '#'\n+\t} | sed -n -e '\n+\t\t${\n+\t\t\ts/^[^ ]* //\n+\t\t\ts|[][*./\\]|\\\\&|g\n+\t\t\ts/^auto$/[#;@!$%^&|:]/\n+\t\t\tp\n+\t\t}'\n+)\"\n+scissors_line=\"^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$\"\n+comment_line=\"^${comment_re}.*\"\n+blank_line='^[ \t]*$'\n+# Disallow lines starting with \"diff -\" or \"Index: \" in the body of the\n+# message. Stop looking if we see a scissors line.\n+line=\"$(sed -n -e \"\n+\t# Skip comments and blank lines at the start of the file.\n+\t/${scissors_line}/q\n+\t/${comment_line}/d\n+\t/${blank_line}/d\n+\t# The first paragraph will become the subject header so\n+\t# does not need to be checked.\n+\t: subject\n+\tn\n+\t/${scissors_line}/q\n+\t/${blank_line}/!b subject\n+\t# Check the body of the message for problematic\n+\t# prefixes.\n+\t: body\n+\tn\n+\t/${scissors_line}/q\n+\t/${comment_line}/b body\n+\t/^diff -/{p;q;}\n+\t/^Index: /{p;q;}\n+\tb body\n+\t\" \"$1\")\"\n+if test -n \"$line\"\n+then\n+\techo >&2 \"Message contains a diff that will confuse 'git am'.\"\n+\techo >&2 \"To fix this indent the diff.\"\n+\tret=1\n+fi\n+\n+exit $ret\n-- \n2.52.0.362.g884e03848a9\n\n"},{"id":"535934","messageId":"0484697e-4c1a-4f23-9cd9-079d92dc8bfd@gmail.com","threadId":"64933","inReplyTo":"xmqqtsvllfdc.fsf@gitster.g","subject":"Re: [PATCH v3] doc: add caveat about round-tripping format-patch","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-13T14:41:43Z","receivedAt":"2026-02-13T14:41:46Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 12/02/2026 23:19, Junio C Hamano wrote:\n> kristofferhaugsbakk@fastmail.com writes:\n> \n>> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>> ...\n>> All of this is covered already, technically. However, we should spell\n>> out the implications.\n> \n> I've read the new text (without formatting, I have to admit) again,\n> and did not see anything questionable.  Nicely written.\n> \n> Shall we mark this for 'next'?\n\nI'm happy with this version - thanks for working on it Kristoffer\n\nPhillip\n\n"},{"id":"535935","messageId":"11522ecc-689d-4136-a7ea-864e1243c2e8@app.fastmail.com","threadId":"64933","inReplyTo":"0484697e-4c1a-4f23-9cd9-079d92dc8bfd@gmail.com","subject":"Re: [PATCH v3] doc: add caveat about round-tripping format-patch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-13T14:43:29Z","receivedAt":"2026-02-13T14:44:48Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Fri, Feb 13, 2026, at 15:41, Phillip Wood wrote:\n> On 12/02/2026 23:19, Junio C Hamano wrote:\n>> kristofferhaugsbakk@fastmail.com writes:\n>>\n>>> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>>> ...\n>>> All of this is covered already, technically. However, we should spell\n>>> out the implications.\n>>\n>> I've read the new text (without formatting, I have to admit) again,\n>> and did not see anything questionable.  Nicely written.\n>>\n>> Shall we mark this for 'next'?\n>\n> I'm happy with this version - thanks for working on it Kristoffer\n\nThanks for the helpful reviews, Phillip and Junio. :)\n\n-- \n  Kristoffer Haugsbakk\n"},{"id":"535941","messageId":"7bf9cdde-de61-46fd-8730-592f87017a19@app.fastmail.com","threadId":"64933","inReplyTo":"494f4df6865f81eba42584ead81327c9a305d0d4.1770993281.git.phillip.wood@dunelm.org.uk","subject":"Re: [PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-13T16:42:41Z","receivedAt":"2026-02-13T16:43:03Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Fri, Feb 13, 2026, at 15:34, Phillip Wood wrote:\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> If the body of a commit message contains a diff that is not indented\n> then \"git am\" will treat that diff as part of the patch rather than\n> as part of the commit message. This allows it to apply email messages\n> that were created by adding a commit message in front of a regular diff\n> without adding the \"---\" separator used by \"git format-patch\". This\n> often surprises users [1-4] so add a check to the sample \"commit-msg\"\n> hook to reject messages that would confuse \"git am\". Even if a project\n> does not use an email based workflow it is not uncommon for people\n> to generate patches from it and apply them with \"git am\". Therefore\n> it is still worth discouraging the creation of commit messages that\n> would not be applied correctly.\n>\n> A further source of confusion when applying patches with \"git am\" is\n> the \"---\" separator that is added by \"git format patch\". If a commit\n> message body contains that line then it will be truncated by \"git am\".\n> As this is often used by patch authors to add some commentary that\n> they do not want to end up in the commit message when the patch is\n> applied, the hook does not complain about the presence of \"---\" lines\n> in the message.\n>\n> Detecting if the message contains a diff is complicated by the\n> hook being passed the message before it is cleaned up so we need to\n> ignore any diffs below the scissors line. There are also two possible\n> config keys to check to find the comment character at the start of\n> the scissors line. The first paragraph of the commit message becomes\n> the email subject header which beings \"Subject: \" and so does not\n> need to be checked. The trailing \".*\" when matching commented lines\n> ensures that if the comment string ends with a \"$\" it is not treated\n> as an anchor.\n>\n> [1]\n> https://lore.kernel.org/git/bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm\n> [2]\n> https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n> [3]\n> https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n> [4]\n> https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  templates/hooks/commit-msg.sample | 54 +++++++++++++++++++++++++++++--\n>  1 file changed, 52 insertions(+), 2 deletions(-)\n>[snip]\n\nThis works for me with `git commit --cleanup=scissors --verbose`.\n"},{"id":"535950","messageId":"xmqqjywgmth6.fsf@gitster.g","threadId":"64933","inReplyTo":"cover.1770993281.git.phillip.wood@dunelm.org.uk","subject":"Re: [PATCH v2 0/2] commit-msg.sample: reject messages that would confuse \"git am\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-13T17:41:25Z","receivedAt":"2026-02-13T17:41:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> This series adds a check to the sample commit-msg hook to reject commit\n> messages where the body of the message contains lines starting with\n> \"diff -\" and \"Index: \". Such lines confuse \"git am\".\n>\n> Changes since V1:\n>\n>  - Allow subjects to start with \"diff -\" as they end up in an email\n>    header and so do not confuse \"git am\"\n>\n>  - Allow \"---\" lines as they are useful when preparing patches.\n\nI see some mention of scissors line that is also new.\n\n"},{"id":"535951","messageId":"xmqqfr74msm9.fsf@gitster.g","threadId":"64933","inReplyTo":"494f4df6865f81eba42584ead81327c9a305d0d4.1770993281.git.phillip.wood@dunelm.org.uk","subject":"Re: [PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-13T17:59:58Z","receivedAt":"2026-02-13T18:00:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> If the body of a commit message contains a diff that is not indented\n> then \"git am\" will treat that diff as part of the patch rather than\n> as part of the commit message. This allows it to apply email messages\n> that were created by adding a commit message in front of a regular diff\n> without adding the \"---\" separator used by \"git format-patch\". This\n> often surprises users [1-4] so add a check to the sample \"commit-msg\"\n> hook to reject messages that would confuse \"git am\". Even if a project\n> does not use an email based workflow it is not uncommon for people\n> to generate patches from it and apply them with \"git am\". Therefore\n> it is still worth discouraging the creation of commit messages that\n> would not be applied correctly.\n>\n> A further source of confusion when applying patches with \"git am\" is\n> the \"---\" separator that is added by \"git format patch\". If a commit\n> message body contains that line then it will be truncated by \"git am\".\n> As this is often used by patch authors to add some commentary that\n> they do not want to end up in the commit message when the patch is\n> applied, the hook does not complain about the presence of \"---\" lines\n> in the message.\n\n\"git format match\" -> \"git format-patch\".\n\n> Detecting if the message contains a diff is complicated by the\n> hook being passed the message before it is cleaned up so we need to\n> ignore any diffs below the scissors line.\n\nSorry, but I do not quite understand the logic here.  In e-mailed\nmessages, the way the scissors line is most commonly used is to have\nsomething like this.\n\n\tHi, I read your problem report, and I think what is going on\n\tis ... (lengthy discussion here).\n\n\tCan you try this patch?\n\n\t--- >8 ---\n\tSubject: frotz: try working around nitfol\n\n\tAs we cannot easily tell if the gostak will distim these\n\tpatciular doshes, let's be careful to see ...\n\n\tdiff - will be used to confuse the mailinfo\n\n\tSigned-off-by: a.u.thour\n\t---\n\t(diffstat here)\n\t(patch here)\n\nand \"diff - will be used to confuse\" is something we would want to\nnotice.  But I am not sure if the use case of committing a scissors\nline.  You help those who write a three-dash line and materials\nmeant to be kept outside of the final commit at the end, so if is\nthis an attempt to help those who write a scissors line and\nmaterials meant to be kept outside of the final commit at the\nbeginning, I can understand, but then don't you want to notice \"diff\n-\" that appears after the scissors line?  I do not offhand remember\nwhat happens to a \"diff -\" that appears before the scissors (i.e.,\nif you write \"diff -\" before \"Can you try this patch?\"), but I\nwouldn't be surprised if mailinfo stopped there long before it sees\nthe scissors.\n\n> There are also two possible\n> config keys to check to find the comment character at the start of\n> the scissors line.\n\nAlso I do not think scissors requires to be a comment.\n\nSo, I am a bit confused.\n\n> The first paragraph of the commit message becomes\n> the email subject header which beings \"Subject: \" and so does not\n> need to be checked.\n\nGreat.\n\n> The trailing \".*\" when matching commented lines\n> ensures that if the comment string ends with a \"$\" it is not treated\n> as an anchor.\n\nI am not sure what this means.  Wouldn't these three\n\n\tsed -e '/^#/d'\n\tsed -e '/^#.*/d'\n\tsed -e '/^#.*$/d'\n\nwork exactly the same way?\n\nThanks.\n\n> [1] https://lore.kernel.org/git/bcqvh7ahjjgzpgxwnr4kh3hfkksfruf54refyry3ha7qk7dldf@fij5calmscvm\n> [2] https://lore.kernel.org/git/ca13705ae4817ffba16f97530637411b59c9eb19.camel@scientia.org/\n> [3] https://lore.kernel.org/git/d0b577825124ac684ab304d3a1395f3d2d0708e8.1662333027.git.matheus.bernardino@usp.br/\n> [4] https://lore.kernel.org/git/CAFOYHZC6Qd9wkoWPcTJDxAs9u=FGpHQTkjE-guhwkya0DRVA6g@mail.gmail.com/\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  templates/hooks/commit-msg.sample | 54 +++++++++++++++++++++++++++++--\n>  1 file changed, 52 insertions(+), 2 deletions(-)\n>\n> diff --git a/templates/hooks/commit-msg.sample b/templates/hooks/commit-msg.sample\n> index b58d1184a9d..f7458efe62f 100755\n> --- a/templates/hooks/commit-msg.sample\n> +++ b/templates/hooks/commit-msg.sample\n> @@ -15,10 +15,60 @@\n>  # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n>  # grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n>  \n> -# This example catches duplicate Signed-off-by lines.\n> +# This example catches duplicate Signed-off-by lines and messages that\n> +# would confuse 'git am'.\n> +\n> +ret=0\n>  \n>  test \"\" = \"$(grep '^Signed-off-by: ' \"$1\" |\n>  \t sort | uniq -c | sed -e '/^[ \t]*1[ \t]/d')\" || {\n>  \techo >&2 Duplicate Signed-off-by lines.\n> -\texit 1\n> +\tret=1\n>  }\n> +\n> +comment_re=\"$(\n> +\t{\n> +\t\tgit config --get-regexp \"^core\\.comment(char|string)\\$\" ||\n> +\t\t\techo '#'\n> +\t} | sed -n -e '\n> +\t\t${\n> +\t\t\ts/^[^ ]* //\n> +\t\t\ts|[][*./\\]|\\\\&|g\n> +\t\t\ts/^auto$/[#;@!$%^&|:]/\n> +\t\t\tp\n> +\t\t}'\n> +)\"\n> +scissors_line=\"^${comment_re} -\\{8,\\} >8 -\\{8,\\}\\$\"\n> +comment_line=\"^${comment_re}.*\"\n> +blank_line='^[ \t]*$'\n> +# Disallow lines starting with \"diff -\" or \"Index: \" in the body of the\n> +# message. Stop looking if we see a scissors line.\n> +line=\"$(sed -n -e \"\n> +\t# Skip comments and blank lines at the start of the file.\n> +\t/${scissors_line}/q\n> +\t/${comment_line}/d\n> +\t/${blank_line}/d\n> +\t# The first paragraph will become the subject header so\n> +\t# does not need to be checked.\n> +\t: subject\n> +\tn\n> +\t/${scissors_line}/q\n> +\t/${blank_line}/!b subject\n> +\t# Check the body of the message for problematic\n> +\t# prefixes.\n> +\t: body\n> +\tn\n> +\t/${scissors_line}/q\n> +\t/${comment_line}/b body\n> +\t/^diff -/{p;q;}\n> +\t/^Index: /{p;q;}\n> +\tb body\n> +\t\" \"$1\")\"\n> +if test -n \"$line\"\n> +then\n> +\techo >&2 \"Message contains a diff that will confuse 'git am'.\"\n> +\techo >&2 \"To fix this indent the diff.\"\n> +\tret=1\n> +fi\n> +\n> +exit $ret\n"},{"id":"535952","messageId":"xmqqbjhsmsin.fsf@gitster.g","threadId":"64933","inReplyTo":"0484697e-4c1a-4f23-9cd9-079d92dc8bfd@gmail.com","subject":"Re: [PATCH v3] doc: add caveat about round-tripping format-patch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-13T18:02:08Z","receivedAt":"2026-02-13T18:02:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> On 12/02/2026 23:19, Junio C Hamano wrote:\n>> kristofferhaugsbakk@fastmail.com writes:\n>> \n>>> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>>> ...\n>>> All of this is covered already, technically. However, we should spell\n>>> out the implications.\n>> \n>> I've read the new text (without formatting, I have to admit) again,\n>> and did not see anything questionable.  Nicely written.\n>> \n>> Shall we mark this for 'next'?\n>\n> I'm happy with this version - thanks for working on it Kristoffer\n>\n> Phillip\n\nThanks for reviewing, Phillip, and thanks for writing, Kristoffer.\n"},{"id":"535953","messageId":"xmqq7bsgms7t.fsf@gitster.g","threadId":"64933","inReplyTo":"7bf9cdde-de61-46fd-8730-592f87017a19@app.fastmail.com","subject":"Re: [PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-13T18:08:38Z","receivedAt":"2026-02-13T18:08:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> writes:\n\n> This works for me with `git commit --cleanup=scissors --verbose`.\n\nAhhhh, OK, my previous message was talking aoubt completely\ndifferent kind of scissors.  Yes, what we take out of the log\nmessage editor will have these \"git commit\" generated comments and\ncrufts, and we do need to strip them out ourselves.\n\nPhillip, sorry for a confused message earlier, and please forget\neverything I said about scissors (I may have said worthy-to-listen\nthings on other things, but I do not offhand recall).\n\nKristoffer, thanks for a review.\n\n"},{"id":"536021","messageId":"20ed1f26-f60b-4e30-a0a5-8bd01dee19d1@gmail.com","threadId":"64933","inReplyTo":"xmqqfr74msm9.fsf@gitster.g","subject":"Re: [PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-14T14:36:39Z","receivedAt":"2026-02-14T14:36:42Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/02/2026 17:59, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> If the body of a commit message contains a diff that is not indented\n>> then \"git am\" will treat that diff as part of the patch rather than\n>> as part of the commit message. This allows it to apply email messages\n>> that were created by adding a commit message in front of a regular diff\n>> without adding the \"---\" separator used by \"git format-patch\". This\n>> often surprises users [1-4] so add a check to the sample \"commit-msg\"\n>> hook to reject messages that would confuse \"git am\". Even if a project\n>> does not use an email based workflow it is not uncommon for people\n>> to generate patches from it and apply them with \"git am\". Therefore\n>> it is still worth discouraging the creation of commit messages that\n>> would not be applied correctly.\n>>\n>> A further source of confusion when applying patches with \"git am\" is\n>> the \"---\" separator that is added by \"git format patch\". If a commit\n>> message body contains that line then it will be truncated by \"git am\".\n>> As this is often used by patch authors to add some commentary that\n>> they do not want to end up in the commit message when the patch is\n>> applied, the hook does not complain about the presence of \"---\" lines\n>> in the message.\n> \n> \"git format match\" -> \"git format-patch\".\n\nThanks (I was confused for a minute because it says \"format patch\" above \nnot \"format match\" but you're pointing out that it should be hypenated)\n\n>> The trailing \".*\" when matching commented lines\n>> ensures that if the comment string ends with a \"$\" it is not treated\n>> as an anchor.\n> \n> I am not sure what this means.  Wouldn't these three\n> \n> \tsed -e '/^#/d'\n> \tsed -e '/^#.*/d'\n> \tsed -e '/^#.*$/d'\n> \n> work exactly the same way?\n\nThey do, but if the comment string is '$' then these two\n\n\tsed -e '/^$/d'\n\tsed -e '/^$.*/d'\n\nhave different meanings\n\nThanks\n\nPhillip\n\n"},{"id":"536022","messageId":"93221c40-90ad-4883-b494-1f74230afe03@gmail.com","threadId":"64933","inReplyTo":"7bf9cdde-de61-46fd-8730-592f87017a19@app.fastmail.com","subject":"Re: [PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-02-14T14:46:56Z","receivedAt":"2026-02-14T14:47:00Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/02/2026 16:42, Kristoffer Haugsbakk wrote:\n> \n> This works for me with `git commit --cleanup=scissors --verbose`.\n\nThanks for testing it.\n\nPhillip\n"},{"id":"536025","messageId":"xmqqh5rjgwld.fsf@gitster.g","threadId":"64933","inReplyTo":"20ed1f26-f60b-4e30-a0a5-8bd01dee19d1@gmail.com","subject":"Re: [PATCH v2 2/2] templates: detect commit messages containing diffs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-14T15:42:54Z","receivedAt":"2026-02-14T15:42:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>>> The trailing \".*\" when matching commented lines\n>>> ensures that if the comment string ends with a \"$\" it is not treated\n>>> as an anchor.\n>> \n>> I am not sure what this means.  Wouldn't these three\n>> \n>> \tsed -e '/^#/d'\n>> \tsed -e '/^#.*/d'\n>> \tsed -e '/^#.*$/d'\n>> \n>> work exactly the same way?\n>\n> They do, but if the comment string is '$' then these two\n>\n> \tsed -e '/^$/d'\n> \tsed -e '/^$.*/d'\n>\n> have different meanings\n\nAhh, that is what you meant.\n\nHaving to write \"/^\\$/\" is inconvenient, because others characters\ndo not generally need the backslash (e.g., \"/^\\#/\" and \"/^#/\" are\nthe same) and some characters even may become nonsensical if we\nblindly add backslash to everybody (e.g., \"/^\\1/\").\n\nNobody would use \"[\" as a commentchar, I hope, as \"/^[/d\" would not\nwork, and neither \"/^[.*/d\" does.\n\nThanks.\n"}]}