[PATCH v4 0/2] format-patch: learn --[no-]range-diff-notes
- From
- kristofferhaugsbakk@fastmail.com <kristofferhaugsbakk@fastmail.com>
- Date
- Oct 4, 2026, 10:17 UTC
- Message-ID
- <V4_CV_format-patch_learn_--range-diff-notes.d5c@m5gid.xyz>
- In-Reply-To
- <CV_format-patch_learn_--range-diff-notes.c57@msgid.xyz>
From: Kristoffer Haugsbakk <code@khaugsbakk.name>
Topic name (applied): kh/format-patch-range-diff-notes
Topic summary: Teach 'format-patch' options to tweak notes output in the range diff independent of what notes are output in the patches.
See patch 2/2 for details.
This is motivated by wanting to turn off range diff notes, but the goal here is to implement it in full generality.
(How many of us `git format-patch --notes` users are there out there? More than a dozen? Maybe just D. Ben Knoble and me?)
I have implemented this behavior for myself and used it for many months. But that was hacky and only suitable for one person’s use. So this is a completely new implementation. In other words: this is new code, *not* tested for months.
§ Changes in v4
Mostly trim expository fat. Also one code refactor. See the patch *notes* for details.
§ Link to v3
https://lore.kernel.org/git/V3_CV_format-patch_learn_--range-diff-notes.d39@m5gid.xyz/
[1/2] format-patch: simplify get_notes_arg parameters [2/2] format-patch: learn --[no-]range-diff-notes
Documentation/git-format-patch.adoc | 11 ++++ builtin/log.c | 50 +++++++++++++++-- t/t3206-range-diff.sh | 86 +++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 6 deletions(-)
Interdiff against v3:
diff --git a/Documentation/git-format-patch.adoc b/Documentation/git-format-patch.adoc index 5907f299a8d..2399ba24454 100644 --- a/Documentation/git-format-patch.adoc +++ b/Documentation/git-format-patch.adoc @@ -384,14 +384,10 @@ sets of patches. range diff. + The default behavior is to display the same notes in the range diff as -on the patches; see `--notes`. But you can use these options to use a -different list of notes. For example, say you have given three notes -refs to `--notes`. At this point those same three notes will be -displayed in the range diff. But then you pass -`--range-diff-notes=<ref>`. Now the range diff will only display -_<ref>_. You can of course pass more refs to this option, just like -`--notes`. And you can also turn off all range diff notes with -`--no-range-diff-notes`. +on the patches; see `--notes`. Use `--range-diff-notes=<ref>` to use +_<ref>_ for the range diff instead. This option can be given multiple +times to show notes from multiple refs. Use `--no-range-diff-notes` to +disable notes in the range diff. `--notes[=<ref>]`:: `--no-notes`:: diff --git a/builtin/log.c b/builtin/log.c index d70101f0755..445400ba782 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1337,27 +1337,15 @@ struct rdiff_notes { }; static int rdiff_notes_cb(const struct option *option, - const char *arg, - int unset) + const char *arg, + int unset) { + struct option opt = *option; struct rdiff_notes *rdiff_notes = option->value; rdiff_notes->override = 1; - - /* - * The rest is the same as - * parse-options-cb.c:parse_opt_string_list - */ - if (unset) { - string_list_clear(&rdiff_notes->notes, 0); - return 0; - } - - if (!arg) - return -1; - - string_list_append(&rdiff_notes->notes, arg); - return 0; + opt.value = &rdiff_notes->notes; + return parse_opt_string_list(&opt, arg, unset); } static int get_notes_refs(struct string_list_item *item, void *arg) Range-diff against v3: 1: 977f9c2e97a ! 1: bb60f300d3f format-patch: simplify get_notes_arg parameters @@ Commit message format-patch: simplify get_notes_arg parameters 85bd88a7 (revision: add rdiff_log_arg to rev_info, 2025-09-25) added - `rdiff_log_arg` to `struct rev_info`. I changed `get_notes_arg` by - simply replacing the first argument with an access on this struct - member. But the second argument was already `struct rev_info`. So I - should have just simplified to *only* passing that parameter. Let’s do - that now. + `rdiff_log_arg` to `struct rev_info`. `get_notes_arg` was changed to + take a second parameter, namely that member: + + get_notes_args(&(rev.rdiff_log_arg), &rev); + + But this is obviously unnecessary; we can just use `&rev`. Now is also a good time to format this `for_each...` line since it’s gotten quite long. @@ Commit message ## Notes (testing) ## + v1: just compile tested ## builtin/log.c ## 2: 748759ca021 ! 2: 4cbd312fec6 format-patch: learn --[no-]range-diff-notes @@ Commit message document the iterations. But including them also includes them in the range diff. And they have nothing useful to say there. - So it would be useful to turn off range diff notes handling with - something like `--no-range-diff-notes`. This could then be turned on - again with `--range-diff-notes`. + Let’s teach git-format-patch(1) `--[no-]range-diff-notes` so that we + can pass in different notes refs to the range diff, or just turn them + off entirely. - An off/on switch is enough for this behavior. However, a bare (no arg) - option (together with the negation) is not consistent with `--[no-]notes - [=<ref>]` and could cause confusion. And we are both conceptually and - literally constructing an argument list to pass on to git-range-diff(1), - which does have the same option format as git-format-patch(1). Moreover, - it is useful to be able to specify exactly what notes you want - git-format-patch(1) and git-range-diff(1) to use.[1] So let’s generalize - it so that you can pass in whatever notes refs you want. + In addition to storing the list of notes, we also need a boolean + `override` to distinguish these two cases: - But now we are faced with a problem that `--notes` does not have; how do - we distinguish an empty `struct string_list` meaning these two things?: - - • No such options given - • `--no-range-diff-notes` - - Well, we can’t. Therefore we need `rdiff_notes.override` to set whenever - any of these options are given. - - † 1: For example, let say we have two notes ref that are used for a - patch series: - - 1. testing. What the user has done to test this iteration. - 2. changelog. The same example from the introduction. - - You could include both notes on the patches but only show `testing` in - the range diff. + 1. No such options were given and empty list (use `--notes`) + 2. Options were given and empty list (`--no-...` given; don’t use notes) *** @@ Commit message Add two tests here for the single-patch case, i.e. the case where the range diff is on the patch and not in the cover letter. These are meant as regression tests based on my encounter with single-patch range diff - notes handling bug.[2] + notes handling bug.[1] - † 2: 155986b4 (format-patch: handle range-diff on notes correctly for + † 1: 155986b4 (format-patch: handle range-diff on notes correctly for single patches, 2025-09-25) + Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> ## Notes (testing) ## - For v3: only compiled and ran `t3206-range-diff`. + v4: + • Compiled and ran `t3206-range-diff`. + • Ran `make html` and looked at git-format-patch(1). ## Documentation/git-format-patch.adoc ## @@ Documentation/git-format-patch.adoc: case is to show comparison with an older iteration of the same @@ Documentation/git-format-patch.adoc: case is to show comparison with an older it + range diff. ++ +The default behavior is to display the same notes in the range diff as -+on the patches; see `--notes`. But you can use these options to use a -+different list of notes. For example, say you have given three notes -+refs to `--notes`. At this point those same three notes will be -+displayed in the range diff. But then you pass -+`--range-diff-notes=<ref>`. Now the range diff will only display -+_<ref>_. You can of course pass more refs to this option, just like -+`--notes`. And you can also turn off all range diff notes with -+`--no-range-diff-notes`. ++on the patches; see `--notes`. Use `--range-diff-notes=<ref>` to use ++_<ref>_ for the range diff instead. This option can be given multiple ++times to show notes from multiple refs. Use `--no-range-diff-notes` to ++disable notes in the range diff. + `--notes[=<ref>]`:: `--no-notes`:: @@ builtin/log.c: static void prepare_cover_text(struct pretty_print_context *pp, +}; + +static int rdiff_notes_cb(const struct option *option, -+ const char *arg, -+ int unset) ++ const char *arg, ++ int unset) +{ ++ struct option opt = *option; + struct rdiff_notes *rdiff_notes = option->value; + + rdiff_notes->override = 1; -+ -+ /* -+ * The rest is the same as -+ * parse-options-cb.c:parse_opt_string_list -+ */ -+ if (unset) { -+ string_list_clear(&rdiff_notes->notes, 0); -+ return 0; -+ } -+ -+ if (!arg) -+ return -1; -+ -+ string_list_append(&rdiff_notes->notes, arg); -+ return 0; ++ opt.value = &rdiff_notes->notes; ++ return parse_opt_string_list(&opt, arg, unset); +} + static int get_notes_refs(struct string_list_item *item, void *arg) base-commit: 1a3e64c6c4a623626ff0687008732a8e007e2a1c
-- 2.55.0.793.gc667de3f2c5