From: Siddharth Asthana Date: Wed, 25 Mar 2026 20:23:50 GMT Subject: [PATCH v6 0/2] replay: add --revert mode to reverse commit changes Message-ID: <20260325202354.10628-1-siddharthasthana31@gmail.com> In-Reply-To: <20260324220401.47040-1-siddharthasthana31@gmail.com> Hi, git replay currently supports cherry-picking (--advance) and rebasing (--onto), but not reverting. We need this at GitLab for Gitaly to reverse commits directly on bare repositories without a checkout. The approach is the same as sequencer.c -- cherry-pick and revert are just the same three-way merge with swapped arguments. We swap the base and pickme trees passed to merge_incore_nonrecursive() to reverse the diff direction. Patch 1 extracts the full revert message formatting logic into a new sequencer_format_revert_message() function that handles everything in one shared function rather than just the header. refer_to_commit() is updated to take a struct repository and a bool instead of replay_opts so it works outside the sequencer. Patch 2 adds --revert as a standalone mode. Reverts are processed newest-first (matching git revert) to reduce conflicts by peeling off changes from the top. The series is based on top of d181b9354c (The 13th batch, 2026-03-07). CI: https://gitlab.com/gitlab-org/git/-/pipelines/2408816732 Changes in v6: - Moved desired_reverse declaration to the top of cmd_replay() with other variable declarations to fix -Wdeclaration-after-statement - Updated doc to mention --revert alongside --advance - Link to v5: https://lore.kernel.org/git/20260324220401.47040-1-siddharthasthana31@gmail.com/ - Link to v4: https://lore.kernel.org/git/20260313054035.26605-1-siddharthasthana31@gmail.com/ - Link to v3: https://public-inbox.org/git/20260218234215.89326-1-siddharthasthana31@gmail.com/ - Link to v2: https://public-inbox.org/git/20251202201611.22137-1-siddharthasthana31@gmail.com/ - Link to v1: https://public-inbox.org/git/20251125170056.34489-1-siddharthasthana31@gmail.com/ Thanks, Siddharth --- Siddharth Asthana (2): sequencer: extract revert message formatting into shared function replay: add --revert mode to reverse commit changes Documentation/git-replay.adoc | 52 +++++++++-- builtin/replay.c | 36 ++++++-- replay.c | 161 +++++++++++++++++++++++++--------- replay.h | 11 ++- sequencer.c | 78 +++++++++------- sequencer.h | 13 +++ t/t3650-replay-basics.sh | 111 +++++++++++++++++++++-- 7 files changed, 361 insertions(+), 101 deletions(-) Range-diff versus v5: 1: 6bd2ce4515 = 1: 6bd2ce4515 sequencer: extract revert message formatting into shared function 2: 9fd92497b9 ! 2: 41fe4861a2 replay: add --revert mode to reverse commit changes @@ Documentation/git-replay.adoc: The history is replayed on top of the an --contained:: Update all branches that point at commits in . Requires `--onto`. +@@ Documentation/git-replay.adoc: The default mode can be configured via the `replay.refAction` configuration vari + + :: + Range of commits to replay; see "Specifying Ranges" in +- linkgit:git-rev-parse[1]. In `--advance ` mode, the +- range should have a single tip, so that it's clear to which tip the +- advanced should point. Any commits in the range whose +- changes are already present in the branch the commits are being ++ linkgit:git-rev-parse[1]. In `--advance ` or ++ `--revert ` mode, the range should have a single tip, ++ so that it's clear to which tip the advanced or reverted ++ should point. Any commits in the range whose changes ++ are already present in the branch the commits are being + replayed onto will be dropped. + + :git-replay: 1 @@ Documentation/git-replay.adoc: When using `--ref-action=print`, the output is usable as input to update refs/heads/branch3 ${NEW_branch3_HASH} ${OLD_branch3_HASH} @@ Documentation/git-replay.adoc: all commits they have since `base`, playing them ## builtin/replay.c ## @@ builtin/replay.c: int cmd_replay(int argc, + struct ref_transaction *transaction = NULL; + struct strbuf transaction_err = STRBUF_INIT; + struct strbuf reflog_msg = STRBUF_INIT; ++ int desired_reverse; + int ret = 0; const char *const replay_usage[] = { N_("(EXPERIMENTAL!) git replay " @@ builtin/replay.c: int cmd_replay(int argc, + * Revert needs newest-first ordering (like git revert) to + * reduce conflicts by peeling off changes from the top. + */ -+ int desired_reverse = !opts.revert; ++ desired_reverse = !opts.revert; + repo_init_revisions(repo, &revs, prefix); base-commit: d181b9354cf85b44455ce3ca9e6af0b9559e0ae2 -- 2.51.0