[PATCH v6 0/2] replay: add --revert mode to reverse commit changes
- From
Siddharth Asthana <siddharthasthana31@gmail.com>
- Date
- Mar 25, 2026, 20:23 UTC
- 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 <branch> 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 <revision-range> 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 <branch> an
--contained::
Update all branches that point at commits in
<revision-range>. Requires `--onto`.
+@@ Documentation/git-replay.adoc: The default mode can be configured via the `replay.refAction` configuration vari
+
+ <revision-range>::
+ Range of commits to replay; see "Specifying Ranges" in
+- linkgit:git-rev-parse[1]. In `--advance <branch>` mode, the
+- range should have a single tip, so that it's clear to which tip the
+- advanced <branch> 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 <branch>` or
++ `--revert <branch>` mode, the range should have a single tip,
++ so that it's clear to which tip the advanced or reverted
++ <branch> 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