{"thread":{"id":"64938","subject":"[PATCH 0/3] doc: patch-id: explain how to map efficiently","startedAt":"2026-02-07T15:06:22Z","lastAt":"2026-02-23T18:06:04Z","messageCount":15,"participants":["kristofferhaugsbakk@fastmail.com","D. Ben Knoble","Kristoffer Haugsbakk","Ben Knoble","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"535420","messageId":"CV_doc_patch-id_4.275@msgid.xyz","threadId":"64938","inReplyTo":null,"subject":"[PATCH 0/3] doc: patch-id: explain how to map efficiently","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T15:05:25Z","receivedAt":"2026-02-07T15:06:22Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\nTopic name: kh/doc-patch-id-4\n\nTopic summary: Explain and emphasize how to map commits efficiently and\nadd an example script.\n\nThis is the fourth patch series for git-patch-id(1). This one focuses on\nemphasizing how the command is an efficient patch ID–commit mapper and\nhow to use the patch IDs to join commits in a script.\n\n• Patch series 1:\n  • Topic: kh/doc-patch-id-markup-fix\n  • https://lore.kernel.org/git/v2-e5ad12cc3b3.1759178715.git.code@khaugsbakk.name/\n• Patch series 2:\n  • Topic: kh/doc-patch-id-1\n  • https://lore.kernel.org/git/v2-38645ea253c.1760369708.git.code@khaugsbakk.name/\n• Patch series 3:\n  • Topic: kh/doc-patch-id\n  • https://lore.kernel.org/git/CV_doc_patch-id_3.1ab@msgid.xyz/\n\nKristoffer Haugsbakk (3):\n  doc: patch-id: emphasize multi-patch processing\n  doc: patch-id: add script example\n  doc: patch-id: see also git-cherry(1)\n\n Documentation/git-patch-id.adoc | 49 +++++++++++++++++++++++++++++++--\n 1 file changed, 46 insertions(+), 3 deletions(-)\n\n\nbase-commit: 67ad42147a7acc2af6074753ebd03d904476118f\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535421","messageId":"multi-patch_processing.276@msgid.xyz","threadId":"64938","inReplyTo":"CV_doc_patch-id_4.275@msgid.xyz","subject":"[PATCH 1/3] doc: patch-id: emphasize multi-patch processing","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T15:05:26Z","receivedAt":"2026-02-07T15:06:40Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\nEmphasize that you can pass multiple patches or diffs to this command.\n\ngit-patch-id(1) is an efficient pID–commit mapper, able to map\nthousands of commits in seconds. But discussions on the command\nseem to typically[1] use the standard loop-over-rev-list-and-\nshell-out pattern:\n\n    for commit in rev-list:\n        prepare a diff from commit | git patch-id\n\nThis is unnecessary; we can bulk-process the patches:\n\n    git rev-list --no-merges <ref> |\n         git diff-tree --patch --stdin |\n         git patch-id --stable\n\nThe first version (translated to shell) takes a little over nine\nminutes for a commit history of about 78K commits.[2] The other one,\nby contrast, takes slightly less than a minute.\n\nAlso drop “the” from “standard input”.\n\n[1]: https://stackoverflow.com/a/19758159\n† 2: This is `master` of this repository on 2025-10-02\n\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n Documentation/git-patch-id.adoc | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex 013e1a61906..e95391cd255 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -3,7 +3,7 @@ git-patch-id(1)\n \n NAME\n ----\n-git-patch-id - Compute unique ID for a patch\n+git-patch-id - Compute unique IDs for patches\n \n SYNOPSIS\n --------\n@@ -12,7 +12,7 @@ git patch-id [--stable | --unstable | --verbatim]\n \n DESCRIPTION\n -----------\n-Read a patch from the standard input and compute the patch ID for it.\n+Read patches from standard input and compute the patch IDs.\n \n A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs associated with a\n patch, with line numbers ignored.  As such, it's \"reasonably stable\", but at\n@@ -25,7 +25,8 @@ When dealing with `git diff-tree --patch` output, it takes advantage of\n the fact that the patch is prefixed with the object name of the\n commit, and outputs two 40-byte hexadecimal strings.  The first\n string is the patch ID, and the second string is the commit ID.\n-This can be used to make a mapping from patch ID to commit ID.\n+This can be used to make a mapping from patch ID to commit ID for a\n+set or range of commits.\n \n OPTIONS\n -------\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535422","messageId":"mapper_example.277@msgid.xyz","threadId":"64938","inReplyTo":"CV_doc_patch-id_4.275@msgid.xyz","subject":"[PATCH 2/3] doc: patch-id: add script example","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T15:05:27Z","receivedAt":"2026-02-07T15:06:59Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\nThe utility and usability of git-patch-id(1) was discussed\nrelatively recently:[1]\n\n    Using \"git patch-id\" is definitely in the \"write a script for it\"\n    category. I don't think I've ever used it as-is from the command\n    line as part of a one-liner. It's very much a command that is\n    designed purely for scripting, the interface is just odd and baroque\n    and doesn't really make sense for one-liners.\n\n    The typical use of patch-id is to generate two *lists* of patch-ids,\n    then sort them and use the patch-id as a key to find commits that\n    look the same.\n\nThe command doc *could* use an example, and since it is a mapper command\nit makes sense for that example to be a little script.\n\nMapping the commits of some branch to an upstream ref allows us to\ndemonstrate generating two lists, sorting them, joining them, and\nfinally discarding the patch ID lookup column with cut(1).\n\n[1]: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n\nInspired-by: Linus Torvalds <torvalds@linux-foundation.org>\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n\nNotes (series):\n    The script will not list the commits in rev-list order because of\n    the sorting.\n\n Documentation/git-patch-id.adoc | 38 +++++++++++++++++++++++++++++++++\n 1 file changed, 38 insertions(+)\n\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex e95391cd255..19780f86425 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -68,6 +68,44 @@ This is the default if `patchid.stable` is set to `true`.\n +\n This is the default.\n \n+EXAMPLES\n+--------\n+\n+linkgit:git-cherry[1] shows what commits from a branch have patch ID\n+equivalent commits in some upstream branch. But it only tells you\n+whether such a commit exists or not. What if you wanted to know the\n+relevant commits in the upstream? We can use this command to make a\n+mapping between your branch and the upstream branch:\n+\n+----\n+#!/bin/sh\n+\n+upstream=\"$1\"\n+branch=\"$2\"\n+test -z \"$branch\" && branch=HEAD\n+limit=\"$3\"\n+if test -n \"$limit\"\n+then\n+    tail_opts=\"$limit\"..\"$upstream\"\n+else\n+    since=$(git log --format=%aI \"$upstream\"..\"$branch\" | tail -1)\n+    tail_opts=--since=\"$since\"' '\"$upstream\"\n+fi\n+for_branch=$(mktemp)\n+for_upstream=$(mktemp)\n+\n+git rev-list --no-merges \"$upstream\"..\"$branch\" |\n+    git diff-tree --patch --stdin |\n+    git patch-id  --stable | sort >\"$for_branch\"\n+git rev-list --no-merges $tail_opts |\n+    git diff-tree --patch --stdin |\n+    git patch-id  --stable | sort >\"$for_upstream\"\n+join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n+----\n+\n+Now the first column shows the commit from your branch and the second\n+column shows the patch ID equivalent commit, if it exists.\n+\n GIT\n ---\n Part of the linkgit:git[1] suite\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535423","messageId":"link_git-cherry.278@msgid.xyz","threadId":"64938","inReplyTo":"CV_doc_patch-id_4.275@msgid.xyz","subject":"[PATCH 3/3] doc: patch-id: see also git-cherry(1)","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T15:05:28Z","receivedAt":"2026-02-07T15:07:17Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\ngit-cherry(1) links to this command. These two commands are similar and\nwe also mention it in the “Examples” section now. Let’s link to it.\n\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n Documentation/git-patch-id.adoc | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex 19780f86425..fb9ec211bb6 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -106,6 +106,10 @@ join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n Now the first column shows the commit from your branch and the second\n column shows the patch ID equivalent commit, if it exists.\n \n+SEE ALSO\n+--------\n+linkgit:git-cherry[1]\n+\n GIT\n ---\n Part of the linkgit:git[1] suite\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"535460","messageId":"CALnO6CC997noiLAFmsy=4DCxc-d5CzaJew0Ri1x6CUtnL4kLXA@mail.gmail.com","threadId":"64938","inReplyTo":"mapper_example.277@msgid.xyz","subject":"Re: [PATCH 2/3] doc: patch-id: add script example","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-02-08T02:34:07Z","receivedAt":"2026-02-08T02:34:19Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Sat, Feb 7, 2026 at 10:07 AM <kristofferhaugsbakk@fastmail.com> wrote:\n>\n> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>\n> The utility and usability of git-patch-id(1) was discussed\n> relatively recently:[1]\n>\n>     Using \"git patch-id\" is definitely in the \"write a script for it\"\n>     category. I don't think I've ever used it as-is from the command\n>     line as part of a one-liner. It's very much a command that is\n>     designed purely for scripting, the interface is just odd and baroque\n>     and doesn't really make sense for one-liners.\n>\n>     The typical use of patch-id is to generate two *lists* of patch-ids,\n>     then sort them and use the patch-id as a key to find commits that\n>     look the same.\n>\n> The command doc *could* use an example, and since it is a mapper command\n> it makes sense for that example to be a little script.\n>\n> Mapping the commits of some branch to an upstream ref allows us to\n> demonstrate generating two lists, sorting them, joining them, and\n> finally discarding the patch ID lookup column with cut(1).\n>\n> [1]: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n>\n> Inspired-by: Linus Torvalds <torvalds@linux-foundation.org>\n> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> ---\n>\n> Notes (series):\n>     The script will not list the commits in rev-list order because of\n>     the sorting.\n>\n>  Documentation/git-patch-id.adoc | 38 +++++++++++++++++++++++++++++++++\n>  1 file changed, 38 insertions(+)\n>\n> diff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\n> index e95391cd255..19780f86425 100644\n> --- a/Documentation/git-patch-id.adoc\n> +++ b/Documentation/git-patch-id.adoc\n> @@ -68,6 +68,44 @@ This is the default if `patchid.stable` is set to `true`.\n>  +\n>  This is the default.\n>\n> +EXAMPLES\n> +--------\n> +\n> +linkgit:git-cherry[1] shows what commits from a branch have patch ID\n> +equivalent commits in some upstream branch. But it only tells you\n> +whether such a commit exists or not. What if you wanted to know the\n> +relevant commits in the upstream? We can use this command to make a\n> +mapping between your branch and the upstream branch:\n> +\n> +----\n> +#!/bin/sh\n> +\n> +upstream=\"$1\"\n> +branch=\"$2\"\n> +test -z \"$branch\" && branch=HEAD\n> +limit=\"$3\"\n> +if test -n \"$limit\"\n> +then\n> +    tail_opts=\"$limit\"..\"$upstream\"\n> +else\n> +    since=$(git log --format=%aI \"$upstream\"..\"$branch\" | tail -1)\n> +    tail_opts=--since=\"$since\"' '\"$upstream\"\n> +fi\n> +for_branch=$(mktemp)\n> +for_upstream=$(mktemp)\n\nDo we want to delete these when we are done (via trap or just cleanup\nat the end)?\n\n> +\n> +git rev-list --no-merges \"$upstream\"..\"$branch\" |\n> +    git diff-tree --patch --stdin |\n> +    git patch-id  --stable | sort >\"$for_branch\"\n> +git rev-list --no-merges $tail_opts |\n> +    git diff-tree --patch --stdin |\n> +    git patch-id  --stable | sort >\"$for_upstream\"\n> +join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n> +----\n> +\n> +Now the first column shows the commit from your branch and the second\n> +column shows the patch ID equivalent commit, if it exists.\n> +\n>  GIT\n>  ---\n>  Part of the linkgit:git[1] suite\n> --\n> 2.53.0.26.g2afa8602a26\n>\n>\n\n\n-- \nD. Ben Knoble\n"},{"id":"535461","messageId":"CALnO6CBnGf6M=a__5mbGNFZ--kDj45nzFBpsv-jPcwO-e5ThOQ@mail.gmail.com","threadId":"64938","inReplyTo":"CV_doc_patch-id_4.275@msgid.xyz","subject":"Re: [PATCH 0/3] doc: patch-id: explain how to map efficiently","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-02-08T02:34:12Z","receivedAt":"2026-02-08T02:34:24Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Sat, Feb 7, 2026 at 10:06 AM <kristofferhaugsbakk@fastmail.com> wrote:\n>\n> From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>\n> Topic name: kh/doc-patch-id-4\n>\n> Topic summary: Explain and emphasize how to map commits efficiently and\n> add an example script.\n>\n> This is the fourth patch series for git-patch-id(1). This one focuses on\n> emphasizing how the command is an efficient patch ID–commit mapper and\n> how to use the patch IDs to join commits in a script.\n>\n> • Patch series 1:\n>   • Topic: kh/doc-patch-id-markup-fix\n>   • https://lore.kernel.org/git/v2-e5ad12cc3b3.1759178715.git.code@khaugsbakk.name/\n> • Patch series 2:\n>   • Topic: kh/doc-patch-id-1\n>   • https://lore.kernel.org/git/v2-38645ea253c.1760369708.git.code@khaugsbakk.name/\n> • Patch series 3:\n>   • Topic: kh/doc-patch-id\n>   • https://lore.kernel.org/git/CV_doc_patch-id_3.1ab@msgid.xyz/\n>\n> Kristoffer Haugsbakk (3):\n>   doc: patch-id: emphasize multi-patch processing\n>   doc: patch-id: add script example\n>   doc: patch-id: see also git-cherry(1)\n>\n>  Documentation/git-patch-id.adoc | 49 +++++++++++++++++++++++++++++++--\n>  1 file changed, 46 insertions(+), 3 deletions(-)\n>\n>\n> base-commit: 67ad42147a7acc2af6074753ebd03d904476118f\n> --\n> 2.53.0.26.g2afa8602a26\n\nShort and sweet with a nice demo of how to use git-patch-id(1). One\nnit on the script, but otherwise LGTM.\n\n\n--\nD. Ben Knoble\n"},{"id":"535485","messageId":"80e4c515-025c-4b10-8405-4363f562f37a@app.fastmail.com","threadId":"64938","inReplyTo":"CALnO6CC997noiLAFmsy=4DCxc-d5CzaJew0Ri1x6CUtnL4kLXA@mail.gmail.com","subject":"Re: [PATCH 2/3] doc: patch-id: add script example","fromName":"Kristoffer Haugsbakk","fromEmail":"code@khaugsbakk.name","sentAt":"2026-02-08T17:23:53Z","receivedAt":"2026-02-08T17:24:14Z","isPatch":true,"sender":{"key":"code@khaugsbakk.name","avatar":"https://avatars.githubusercontent.com/u/2229597?v=4"},"body":"On Sun, Feb 8, 2026, at 03:34, D. Ben Knoble wrote:\n>>[snip]\n>> +#!/bin/sh\n>> +\n>> +upstream=\"$1\"\n>> +branch=\"$2\"\n>> +test -z \"$branch\" && branch=HEAD\n>> +limit=\"$3\"\n>> +if test -n \"$limit\"\n>> +then\n>> +    tail_opts=\"$limit\"..\"$upstream\"\n>> +else\n>> +    since=$(git log --format=%aI \"$upstream\"..\"$branch\" | tail -1)\n>> +    tail_opts=--since=\"$since\"' '\"$upstream\"\n>> +fi\n>> +for_branch=$(mktemp)\n>> +for_upstream=$(mktemp)\n>\n> Do we want to delete these when we are done (via trap or just cleanup\n> at the end)?\n\nSounds good. Maybe just at the end since this is a happy-path example\nscript. ;) (not very robust and all that)\n\n>\n>[snip]\n"},{"id":"536016","messageId":"V2_CV_doc_patch-id_4.371@msgid.xyz","threadId":"64938","inReplyTo":"CV_doc_patch-id_4.275@msgid.xyz","subject":"[PATCH v2 0/3] doc: patch-id: explain how to map efficiently","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-14T11:55:40Z","receivedAt":"2026-02-14T11:56:27Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\nTopic name (applied): kh/doc-patch-id-4\n\nTopic summary: Explain and emphasize how to map commits efficiently and\nadd an example script.\n\nThis is the fourth patch series for git-patch-id(1). This one focuses on\nemphasizing how the command is an efficient patch ID–commit mapper and\nhow to use the patch IDs to join commits in a script.\n\n§ Changes in v2\n\n• Delete temporary files at the end of the script.\n• Consistent footnote style: https://lore.kernel.org/git/c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com/\n\n§ Previous patch series\n\n• Patch series 1:\n  • Topic: kh/doc-patch-id-markup-fix\n  • https://lore.kernel.org/git/v2-e5ad12cc3b3.1759178715.git.code@khaugsbakk.name/\n• Patch series 2:\n  • Topic: kh/doc-patch-id-1\n  • https://lore.kernel.org/git/v2-38645ea253c.1760369708.git.code@khaugsbakk.name/\n• Patch series 3:\n  • Topic: kh/doc-patch-id\n  • https://lore.kernel.org/git/CV_doc_patch-id_3.1ab@msgid.xyz/\n\nLink to v1: https://lore.kernel.org/git/CV_doc_patch-id_4.275@msgid.xyz/#t\n\nKristoffer Haugsbakk (3):\n  doc: patch-id: emphasize multi-patch processing\n  doc: patch-id: add script example\n  doc: patch-id: see also git-cherry(1)\n\n Documentation/git-patch-id.adoc | 51 +++++++++++++++++++++++++++++++--\n 1 file changed, 48 insertions(+), 3 deletions(-)\n\nInterdiff against v1:\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex fb9ec211bb6..05859990c8e 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -101,6 +101,8 @@ git rev-list --no-merges $tail_opts |\n     git diff-tree --patch --stdin |\n     git patch-id  --stable | sort >\"$for_upstream\"\n join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n+rm \"$for_branch\"\n+rm \"$for_upstream\"\n ----\n \n Now the first column shows the commit from your branch and the second\nRange-diff against v1:\n1:  704dc0ada8f ! 1:  e9319039d5e doc: patch-id: emphasize multi-patch processing\n    @@ Commit message\n     \n         Also drop “the” from “standard input”.\n     \n    -    [1]: https://stackoverflow.com/a/19758159\n    +    † 1: https://stackoverflow.com/a/19758159\n         † 2: This is `master` of this repository on 2025-10-02\n     \n         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n2:  e37c25aa5fc ! 2:  8ba3e71752c doc: patch-id: add script example\n    @@ Commit message\n         demonstrate generating two lists, sorting them, joining them, and\n         finally discarding the patch ID lookup column with cut(1).\n     \n    -    [1]: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n    +    † 1: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n     \n         Inspired-by: Linus Torvalds <torvalds@linux-foundation.org>\n         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n    @@ Documentation/git-patch-id.adoc: This is the default if `patchid.stable` is set\n     +    git diff-tree --patch --stdin |\n     +    git patch-id  --stable | sort >\"$for_upstream\"\n     +join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n    ++rm \"$for_branch\"\n    ++rm \"$for_upstream\"\n     +----\n     +\n     +Now the first column shows the commit from your branch and the second\n3:  2a319a43b2e ! 3:  27cad849312 doc: patch-id: see also git-cherry(1)\n    @@ Commit message\n         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n     \n      ## Documentation/git-patch-id.adoc ##\n    -@@ Documentation/git-patch-id.adoc: join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n    +@@ Documentation/git-patch-id.adoc: rm \"$for_upstream\"\n      Now the first column shows the commit from your branch and the second\n      column shows the patch ID equivalent commit, if it exists.\n      \n\nbase-commit: 67ad42147a7acc2af6074753ebd03d904476118f\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"536017","messageId":"V2_multi-patch_processing.372@msgid.xyz","threadId":"64938","inReplyTo":"V2_CV_doc_patch-id_4.371@msgid.xyz","subject":"[PATCH v2 1/3] doc: patch-id: emphasize multi-patch processing","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-14T11:55:41Z","receivedAt":"2026-02-14T11:56:46Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\nEmphasize that you can pass multiple patches or diffs to this command.\n\ngit-patch-id(1) is an efficient pID–commit mapper, able to map\nthousands of commits in seconds. But discussions on the command\nseem to typically[1] use the standard loop-over-rev-list-and-\nshell-out pattern:\n\n    for commit in rev-list:\n        prepare a diff from commit | git patch-id\n\nThis is unnecessary; we can bulk-process the patches:\n\n    git rev-list --no-merges <ref> |\n         git diff-tree --patch --stdin |\n         git patch-id --stable\n\nThe first version (translated to shell) takes a little over nine\nminutes for a commit history of about 78K commits.[2] The other one,\nby contrast, takes slightly less than a minute.\n\nAlso drop “the” from “standard input”.\n\n† 1: https://stackoverflow.com/a/19758159\n† 2: This is `master` of this repository on 2025-10-02\n\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n\nNotes (series):\n    v2: Use my weird daggers consistently for footnotes\n\n Documentation/git-patch-id.adoc | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex 013e1a61906..e95391cd255 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -3,7 +3,7 @@ git-patch-id(1)\n \n NAME\n ----\n-git-patch-id - Compute unique ID for a patch\n+git-patch-id - Compute unique IDs for patches\n \n SYNOPSIS\n --------\n@@ -12,7 +12,7 @@ git patch-id [--stable | --unstable | --verbatim]\n \n DESCRIPTION\n -----------\n-Read a patch from the standard input and compute the patch ID for it.\n+Read patches from standard input and compute the patch IDs.\n \n A \"patch ID\" is nothing but a sum of SHA-1 of the file diffs associated with a\n patch, with line numbers ignored.  As such, it's \"reasonably stable\", but at\n@@ -25,7 +25,8 @@ When dealing with `git diff-tree --patch` output, it takes advantage of\n the fact that the patch is prefixed with the object name of the\n commit, and outputs two 40-byte hexadecimal strings.  The first\n string is the patch ID, and the second string is the commit ID.\n-This can be used to make a mapping from patch ID to commit ID.\n+This can be used to make a mapping from patch ID to commit ID for a\n+set or range of commits.\n \n OPTIONS\n -------\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"536018","messageId":"V2_mapper_example.373@msgid.xyz","threadId":"64938","inReplyTo":"V2_CV_doc_patch-id_4.371@msgid.xyz","subject":"[PATCH v2 2/3] doc: patch-id: add script example","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-14T11:55:42Z","receivedAt":"2026-02-14T11:57:04Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\nThe utility and usability of git-patch-id(1) was discussed\nrelatively recently:[1]\n\n    Using \"git patch-id\" is definitely in the \"write a script for it\"\n    category. I don't think I've ever used it as-is from the command\n    line as part of a one-liner. It's very much a command that is\n    designed purely for scripting, the interface is just odd and baroque\n    and doesn't really make sense for one-liners.\n\n    The typical use of patch-id is to generate two *lists* of patch-ids,\n    then sort them and use the patch-id as a key to find commits that\n    look the same.\n\nThe command doc *could* use an example, and since it is a mapper command\nit makes sense for that example to be a little script.\n\nMapping the commits of some branch to an upstream ref allows us to\ndemonstrate generating two lists, sorting them, joining them, and\nfinally discarding the patch ID lookup column with cut(1).\n\n† 1: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n\nInspired-by: Linus Torvalds <torvalds@linux-foundation.org>\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n\nNotes (series):\n    v2:\n    • Delete temporary files\n    • Use my weird daggers consistently for footnotes\n    v1:\n    The script will not list the commits in rev-list order because of\n    the sorting.\n\n Documentation/git-patch-id.adoc | 40 +++++++++++++++++++++++++++++++++\n 1 file changed, 40 insertions(+)\n\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex e95391cd255..1618994e76c 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -68,6 +68,46 @@ This is the default if `patchid.stable` is set to `true`.\n +\n This is the default.\n \n+EXAMPLES\n+--------\n+\n+linkgit:git-cherry[1] shows what commits from a branch have patch ID\n+equivalent commits in some upstream branch. But it only tells you\n+whether such a commit exists or not. What if you wanted to know the\n+relevant commits in the upstream? We can use this command to make a\n+mapping between your branch and the upstream branch:\n+\n+----\n+#!/bin/sh\n+\n+upstream=\"$1\"\n+branch=\"$2\"\n+test -z \"$branch\" && branch=HEAD\n+limit=\"$3\"\n+if test -n \"$limit\"\n+then\n+    tail_opts=\"$limit\"..\"$upstream\"\n+else\n+    since=$(git log --format=%aI \"$upstream\"..\"$branch\" | tail -1)\n+    tail_opts=--since=\"$since\"' '\"$upstream\"\n+fi\n+for_branch=$(mktemp)\n+for_upstream=$(mktemp)\n+\n+git rev-list --no-merges \"$upstream\"..\"$branch\" |\n+    git diff-tree --patch --stdin |\n+    git patch-id  --stable | sort >\"$for_branch\"\n+git rev-list --no-merges $tail_opts |\n+    git diff-tree --patch --stdin |\n+    git patch-id  --stable | sort >\"$for_upstream\"\n+join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n+rm \"$for_branch\"\n+rm \"$for_upstream\"\n+----\n+\n+Now the first column shows the commit from your branch and the second\n+column shows the patch ID equivalent commit, if it exists.\n+\n GIT\n ---\n Part of the linkgit:git[1] suite\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"536019","messageId":"V2_link_git-cherry.374@msgid.xyz","threadId":"64938","inReplyTo":"V2_CV_doc_patch-id_4.371@msgid.xyz","subject":"[PATCH v2 3/3] doc: patch-id: see also git-cherry(1)","fromName":"","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-14T11:55:43Z","receivedAt":"2026-02-14T11:57:24Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n\ngit-cherry(1) links to this command. These two commands are similar and\nwe also mention it in the “Examples” section now. Let’s link to it.\n\nSigned-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n---\n Documentation/git-patch-id.adoc | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\nindex 1618994e76c..05859990c8e 100644\n--- a/Documentation/git-patch-id.adoc\n+++ b/Documentation/git-patch-id.adoc\n@@ -108,6 +108,10 @@ rm \"$for_upstream\"\n Now the first column shows the commit from your branch and the second\n column shows the patch ID equivalent commit, if it exists.\n \n+SEE ALSO\n+--------\n+linkgit:git-cherry[1]\n+\n GIT\n ---\n Part of the linkgit:git[1] suite\n-- \n2.53.0.26.g2afa8602a26\n\n"},{"id":"536029","messageId":"69F74ACB-93A4-4FB9-AE0D-57C433448981@gmail.com","threadId":"64938","inReplyTo":"V2_CV_doc_patch-id_4.371@msgid.xyz","subject":"Re: [PATCH v2 0/3] doc: patch-id: explain how to map efficiently","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-02-14T20:00:14Z","receivedAt":"2026-02-14T20:00:27Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"\n> Le 14 févr. 2026 à 06:56, kristofferhaugsbakk@fastmail.com a écrit :\n> \n> ﻿From: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> \n> Topic name (applied): kh/doc-patch-id-4\n> \n> Topic summary: Explain and emphasize how to map commits efficiently and\n> add an example script.\n> \n> This is the fourth patch series for git-patch-id(1). This one focuses on\n> emphasizing how the command is an efficient patch ID–commit mapper and\n> how to use the patch IDs to join commits in a script.\n> \n> § Changes in v2\n> \n> • Delete temporary files at the end of the script.\n> • Consistent footnote style: https://lore.kernel.org/git/c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com/\n> \n> § Previous patch series\n> \n> • Patch series 1:\n>  • Topic: kh/doc-patch-id-markup-fix\n>  • https://lore.kernel.org/git/v2-e5ad12cc3b3.1759178715.git.code@khaugsbakk.name/\n> • Patch series 2:\n>  • Topic: kh/doc-patch-id-1\n>  • https://lore.kernel.org/git/v2-38645ea253c.1760369708.git.code@khaugsbakk.name/\n> • Patch series 3:\n>  • Topic: kh/doc-patch-id\n>  • https://lore.kernel.org/git/CV_doc_patch-id_3.1ab@msgid.xyz/\n> \n> Link to v1: https://lore.kernel.org/git/CV_doc_patch-id_4.275@msgid.xyz/#t\n> \n> Kristoffer Haugsbakk (3):\n>  doc: patch-id: emphasize multi-patch processing\n>  doc: patch-id: add script example\n>  doc: patch-id: see also git-cherry(1)\n> \n> Documentation/git-patch-id.adoc | 51 +++++++++++++++++++++++++++++++--\n> 1 file changed, 48 insertions(+), 3 deletions(-)\n> \n> Interdiff against v1:\n> diff --git a/Documentation/git-patch-id.adoc b/Documentation/git-patch-id.adoc\n> index fb9ec211bb6..05859990c8e 100644\n> --- a/Documentation/git-patch-id.adoc\n> +++ b/Documentation/git-patch-id.adoc\n> @@ -101,6 +101,8 @@ git rev-list --no-merges $tail_opts |\n>     git diff-tree --patch --stdin |\n>     git patch-id  --stable | sort >\"$for_upstream\"\n> join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n> +rm \"$for_branch\"\n> +rm \"$for_upstream\"\n> ----\n> \n> Now the first column shows the commit from your branch and the second\n> Range-diff against v1:\n> 1:  704dc0ada8f ! 1:  e9319039d5e doc: patch-id: emphasize multi-patch processing\n>    @@ Commit message\n> \n>         Also drop “the” from “standard input”.\n> \n>    -    [1]: https://stackoverflow.com/a/19758159\n>    +    † 1: https://stackoverflow.com/a/19758159\n>         † 2: This is `master` of this repository on 2025-10-02\n> \n>         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> 2:  e37c25aa5fc ! 2:  8ba3e71752c doc: patch-id: add script example\n>    @@ Commit message\n>         demonstrate generating two lists, sorting them, joining them, and\n>         finally discarding the patch ID lookup column with cut(1).\n> \n>    -    [1]: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n>    +    † 1: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n> \n>         Inspired-by: Linus Torvalds <torvalds@linux-foundation.org>\n>         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n>    @@ Documentation/git-patch-id.adoc: This is the default if `patchid.stable` is set\n>     +    git diff-tree --patch --stdin |\n>     +    git patch-id  --stable | sort >\"$for_upstream\"\n>     +join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n>    ++rm \"$for_branch\"\n>    ++rm \"$for_upstream\"\n>     +----\n>     +\n>     +Now the first column shows the commit from your branch and the second\n> 3:  2a319a43b2e ! 3:  27cad849312 doc: patch-id: see also git-cherry(1)\n>    @@ Commit message\n>         Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>\n> \n>      ## Documentation/git-patch-id.adoc ##\n>    -@@ Documentation/git-patch-id.adoc: join -a1 \"$for_branch\" \"$for_upstream\" | cut -d' ' -f2,3\n>    +@@ Documentation/git-patch-id.adoc: rm \"$for_upstream\"\n>      Now the first column shows the commit from your branch and the second\n>      column shows the patch ID equivalent commit, if it exists.\n> \n> \n> base-commit: 67ad42147a7acc2af6074753ebd03d904476118f\n> --\n> 2.53.0.26.g2afa8602a26\n> \n\nLooks like my comments were well-addressed, thanks! Looks good. "},{"id":"536555","messageId":"xmqq1pifvyhm.fsf@gitster.g","threadId":"64938","inReplyTo":"V2_CV_doc_patch-id_4.371@msgid.xyz","subject":"Re: [PATCH v2 0/3] doc: patch-id: explain how to map efficiently","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-20T22:31:01Z","receivedAt":"2026-02-20T22:31:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"kristofferhaugsbakk@fastmail.com writes:\n\n> This is the fourth patch series for git-patch-id(1). This one focuses on\n> emphasizing how the command is an efficient patch ID–commit mapper and\n> how to use the patch IDs to join commits in a script.\n>\n> § Changes in v2\n>\n> • Delete temporary files at the end of the script.\n> • Consistent footnote style: https://lore.kernel.org/git/c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com/\n\nThe latest iteration of this series has seen no responses.  Is\neverybody happy with them?\n\nThanks.\n"},{"id":"536571","messageId":"F628C3EE-0600-419E-8D85-0CEA9EEA2243@gmail.com","threadId":"64938","inReplyTo":"xmqq1pifvyhm.fsf@gitster.g","subject":"Re: [PATCH v2 0/3] doc: patch-id: explain how to map efficiently","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-02-21T02:38:15Z","receivedAt":"2026-02-21T02:38:27Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"\n> Le 20 févr. 2026 à 17:31, Junio C Hamano <gitster@pobox.com> a écrit :\n> \n> ﻿kristofferhaugsbakk@fastmail.com writes:\n> \n>> This is the fourth patch series for git-patch-id(1). This one focuses on\n>> emphasizing how the command is an efficient patch ID–commit mapper and\n>> how to use the patch IDs to join commits in a script.\n>> \n>> § Changes in v2\n>> \n>> • Delete temporary files at the end of the script.\n>> • Consistent footnote style: https://lore.kernel.org/git/c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com/\n> \n> The latest iteration of this series has seen no responses.  Is\n> everybody happy with them?\n> \n> Thanks.\n\nNo /further/ responses, perhaps? Unless my mail didn’t come through. I completely understand if my approval was not weighted particularly highly, though, ;)"},{"id":"536864","messageId":"af41be2a-daac-4d23-852d-61ff7e0dae6d@app.fastmail.com","threadId":"64938","inReplyTo":"F628C3EE-0600-419E-8D85-0CEA9EEA2243@gmail.com","subject":"Re: [PATCH v2 0/3] doc: patch-id: explain how to map efficiently","fromName":"Kristoffer Haugsbakk","fromEmail":"code@khaugsbakk.name","sentAt":"2026-02-23T18:04:01Z","receivedAt":"2026-02-23T18:06:04Z","isPatch":true,"sender":{"key":"code@khaugsbakk.name","avatar":"https://avatars.githubusercontent.com/u/2229597?v=4"},"body":"On Sat, Feb 21, 2026, at 03:38, Ben Knoble wrote:\n>> Le 20 févr. 2026 à 17:31, Junio C Hamano <gitster@pobox.com> a écrit :\n>>\n>> ﻿kristofferhaugsbakk@fastmail.com writes:\n>>\n>>> This is the fourth patch series for git-patch-id(1). This one focuses on\n>>> emphasizing how the command is an efficient patch ID–commit mapper and\n>>> how to use the patch IDs to join commits in a script.\n>>>\n>>> § Changes in v2\n>>>\n>>> • Delete temporary files at the end of the script.\n>>> • Consistent footnote style: https://lore.kernel.org/git/c70adde6-e3db-4a46-bb29-a19d7aba8c7e@app.fastmail.com/\n>>\n>> The latest iteration of this series has seen no responses.  Is\n>> everybody happy with them?\n>>\n>> Thanks.\n>\n> No /further/ responses, perhaps? Unless my mail didn’t come through. I\n> completely understand if my approval was not weighted particularly\n> highly, though, ;)\n\nThanks for following this series.\n\nI was wondering if a relatively lengthy example like that would be\naccepted on such a small (doc footprint) command. I was ready to drop\nthat example patch/commit if the series didn’t move ahead.\n\nIn general *I* would like to see more examples and discussions in the\ndocs where commands that are better used in conjunction with other Git\ncommands and general utilities (c.f. git-commit(1), git-tag(1),\n...). And in this case, this “write a script for it” command, as it was\ncalled in the linked email,[1] seemed like a good candidate.\n\n† 1: https://lore.kernel.org/workflows/CAHk-=wiN+8EUoik4UeAJ-HPSU7hczQP+8+_uP3vtAy_=YfJ9PQ@mail.gmail.com/\n\nIt’s a bit hard to find information on this on the Web, I think, because\n“Git plumbing” has been SEO’ed into the silo of “here’s how you can use\nthree Git plumbing commands to do what you can do in one Git porcelain\ncommand”.\n\nBut I also can understand if others think (maybe?) think that this would\nbe too much verbiage.\n\nBut I see that this is in `next` now. Which I am glad to see of course.\n"}]}