sequencer: extract revert message formatting into shared function

The logic for formatting revert commit messages (handling "Revert" and "Reapply" cases, appending "This reverts commit <ref>.", and handling merge-parent references) currently lives inline in do_pick_commit(). The upcoming replay --revert mode needs to reuse this logic. Extract all of this into a new sequencer_format_revert_message() function. The function takes a repository, the subject line, commit, parent, a use_commit_reference flag, and the output strbuf. It handles both regular reverts ("Revert "<subject>"") and revert-of-revert cases ("Reapply "<subject>""), and uses refer_to_commit() internally to format the commit reference. Update refer_to_commit() to take a struct repository parameter instead of relying on the_repository, and a bool instead of reading from replay_opts directly. This makes it usable from the new shared function without pulling in sequencer-specific state. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Siddharth Asthana committed Mar 26, 2026 at 01:53 UTC 1e6434ebbd63d4ec0ad2f8bccf25bd0d98d55030
2 files changed +59 -32
sequencer.c
+46 -32
@@ -2198,15 +2198,16 @@ static int should_edit(struct replay_opts *opts) {
2198 return opts->edit;
2199 }
2200
2201 -static void refer_to_commit(struct replay_opts *opts,
2202 - struct strbuf *msgbuf, struct commit *commit)
2201 +static void refer_to_commit(struct repository *r, struct strbuf *msgbuf,
2202 + const struct commit *commit,
2203 + bool use_commit_reference)
2204 {
2204 - if (opts->commit_use_reference) {
2205 + if (use_commit_reference) {
2206 struct pretty_print_context ctx = {
2207 .abbrev = DEFAULT_ABBREV,
2208 .date_mode.type = DATE_SHORT,
2209 };
2209 - repo_format_commit_message(the_repository, commit,
2210 + repo_format_commit_message(r, commit,
2211 "%h (%s, %ad)", msgbuf, &ctx);
2212 } else {
2213 strbuf_addstr(msgbuf, oid_to_hex(&commit->object.oid));
@@ -2356,38 +2357,14 @@ static int do_pick_commit(struct repository *r,
2357 */
2358
2359 if (command == TODO_REVERT) {
2359 - const char *orig_subject;
2360 -
2360 base = commit;
2361 base_label = msg.label;
2362 next = parent;
2363 next_label = msg.parent_label;
2365 - if (opts->commit_use_reference) {
2366 - strbuf_commented_addf(&ctx->message, comment_line_str,
2367 - "*** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
2368 - } else if (skip_prefix(msg.subject, "Revert \"", &orig_subject) &&
2369 - /*
2370 - * We don't touch pre-existing repeated reverts, because
2371 - * theoretically these can be nested arbitrarily deeply,
2372 - * thus requiring excessive complexity to deal with.
2373 - */
2374 - !starts_with(orig_subject, "Revert \"")) {
2375 - strbuf_addstr(&ctx->message, "Reapply \"");
2376 - strbuf_addstr(&ctx->message, orig_subject);
2377 - strbuf_addstr(&ctx->message, "\n");
2378 - } else {
2379 - strbuf_addstr(&ctx->message, "Revert \"");
2380 - strbuf_addstr(&ctx->message, msg.subject);
2381 - strbuf_addstr(&ctx->message, "\"\n");
2382 - }
2383 - strbuf_addstr(&ctx->message, "\nThis reverts commit ");
2384 - refer_to_commit(opts, &ctx->message, commit);
2385 -
2386 - if (commit->parents && commit->parents->next) {
2387 - strbuf_addstr(&ctx->message, ", reversing\nchanges made to ");
2388 - refer_to_commit(opts, &ctx->message, parent);
2389 - }
2390 - strbuf_addstr(&ctx->message, ".\n");
2364 + sequencer_format_revert_message(r, msg.subject, commit,
2365 + parent,
2366 + opts->commit_use_reference,
2367 + &ctx->message);
2368 } else {
2369 const char *p;
2370
@@ -5572,6 +5549,43 @@ out:
5549 return res;
5550 }
5551
5552 +void sequencer_format_revert_message(struct repository *r,
5553 + const char *subject,
5554 + const struct commit *commit,
5555 + const struct commit *parent,
5556 + bool use_commit_reference,
5557 + struct strbuf *message)
5558 +{
5559 + const char *orig_subject;
5560 +
5561 + if (use_commit_reference) {
5562 + strbuf_commented_addf(message, comment_line_str,
5563 + "*** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
5564 + } else if (skip_prefix(subject, "Revert \"", &orig_subject) &&
5565 + /*
5566 + * We don't touch pre-existing repeated reverts, because
5567 + * theoretically these can be nested arbitrarily deeply,
5568 + * thus requiring excessive complexity to deal with.
5569 + */
5570 + !starts_with(orig_subject, "Revert \"")) {
5571 + strbuf_addstr(message, "Reapply \"");
5572 + strbuf_addstr(message, orig_subject);
5573 + strbuf_addstr(message, "\n");
5574 + } else {
5575 + strbuf_addstr(message, "Revert \"");
5576 + strbuf_addstr(message, subject);
5577 + strbuf_addstr(message, "\"\n");
5578 + }
5579 + strbuf_addstr(message, "\nThis reverts commit ");
5580 + refer_to_commit(r, message, commit, use_commit_reference);
5581 +
5582 + if (commit->parents && commit->parents->next) {
5583 + strbuf_addstr(message, ", reversing\nchanges made to ");
5584 + refer_to_commit(r, message, parent, use_commit_reference);
5585 + }
5586 + strbuf_addstr(message, ".\n");
5587 +}
5588 +
5589 void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
5590 {
5591 unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
sequencer.h
+13
@@ -271,4 +271,17 @@ int sequencer_determine_whence(struct repository *r, enum commit_whence *whence)
271 */
272 int sequencer_get_update_refs_state(const char *wt_dir, struct string_list *refs);
273
274 +/*
275 + * Format a revert commit message with appropriate 'Revert "<subject>"' or
276 + * 'Reapply "<subject>"' prefix and 'This reverts commit <ref>.' body.
277 + * When use_commit_reference is set, <ref> is an abbreviated hash with
278 + * subject and date; otherwise the full hex hash is used.
279 + */
280 +void sequencer_format_revert_message(struct repository *r,
281 + const char *subject,
282 + const struct commit *commit,
283 + const struct commit *parent,
284 + bool use_commit_reference,
285 + struct strbuf *message);
286 +
287 #endif /* SEQUENCER_H */