From: Toon Claes <toon@iotcl.com>
To: Justin Tobler <jltobler@gmail.com>
Cc: git@vger.kernel.org,
Siddharth Asthana <siddharthasthana31@gmail.com>,
Christian Couder <chriscool@tuxfamily.org>
Subject: Re: [PATCH RFC] git-replay: implement subcommands
Date: Fri, 13 Mar 2026 17:22:48 +0100 [thread overview]
Message-ID: <87v7ezsnqf.fsf@iotcl.com> (raw)
In-Reply-To: <abGutGnWo1gN0Dii@denethor>
Justin Tobler <jltobler@gmail.com> writes:
> On 26/03/09 08:30PM, Toon Claes wrote:
>> git-replay(1) has various operation modes. The mode depends on which of
>> the options `--onto`, `--advance`, or `--revert` is given. These options
>> are mutually exclusive. This usage pattern is counterintuitive and
>> uncommon for Git commands to behave this way.
>>
>> Implement subcommands into git-replay(1):
>>
>> * `rebase`: This replaces what `--onto=` used to do.
>
> I'm a bit confused by this. It appears that the "rebase" subcommand
> still requires the `--onto` option so it doesn't seem to really be
> replacing anything. I assume we are tyring to break these operations
> into distinct categories which seems reasonable.
Okay, maybe I should be more verbose about the problem I'm trying to
solve.
Let's start with the existing option `--onto`. This implies a "rebase"
operation. The argument to this option is a revision which acts as the
base for the rebase. On this base the commits in the revision-range are
replayed.
In the end, git-replay(1) takes the ref from the upper boundary of this
revision-range, and updates that to the result of the rebase.
A usage example:
$ git replay --onto=master master..my-branch
With option --ref-action=print, you'll get:
update refs/heads/my-branch aaabbbccc 000111222
(using abbreviated OIDs for simplification in this email)
So 000111222 would be the commit my-branch is pointing to before the
git-replay(1), and aaabbbccc the new commit.
Now looking at `--advance`, this works differently:
$ git replay --advance=other-branch master..my-branch
With option --ref-action=print, you'll get:
update refs/heads/other-branch 888999000 444555666
As you can see, the argument of --advance is the ref that gets updated.
So this command would be identical to:
$ git replay --advance=other-branch master..000111222
If we try to do use the commit OID in the revision-range when using
--onto:
$ git replay --onto=master master..000111222
Nothing (noticable) happens. git-replay(1) does the replay, but doesn't
know which ref to update.
This assymetry between --onto and --revert & --advance is the main issue
I'm trying to resolve with this proposal.
>> * `pick`: This replaces what `--advance=` used to do.
>> * `revert`: This replaces what `--revert=` used to do.
>>
>> Option `--onto` is still accepted. It's mandatory for the `rebase`
>> subcommand and needs to be used in the exact same way.
>>
>> Option `--ref` is added and required for the `pick` and `revert`
>> subcommands. This replaces what `--advance` and `--revert` used to do,
>> but as a single uniform option for all subcommands.
>>
>> The `rebase` subcommand also accepts option `--ref`, and when given this
>> is the ref that's updated with the outcome of the git-replay(1) command.
>> Thus following commands are identical:
>>
>> $ git replay rebase --onto=master master..branch-1
>>
>> $ git replay rebase --onto=master master..branch-1^{0} --ref=refs/heads/branch-1
>>
>> In the second example the upper boundary of the revision range is peeled
>> down to a commit (using '^{0}'). Without option `--ref`, git-replay(1)
>> doesn't know which ref to update, that's why `--ref` is passed
>> explicitly.
>>
>> For the subcommands `pick` and `revert` it's also possible to combine
>> `--ref` and `--onto`. Here are again two identical examples:
>>
>> $ git replay pick --onto=branch-1 master..aabbccdd
>>
>> $ git replay pick --onto=branch-1^{0} master..aabbccdd --ref=refs/heads/branch-1
>>
>> In the latter the argument for `--onto` is peeled down to a commit, so
>> the command doesn't know which ref to update. To inform git-replay(1)
>> which refs should be updated, it's passed explicitly as option `--ref`.
>>
>> Signed-off-by: Toon Claes <toon@iotcl.com>
>> ---
>> In the patch series by Siddharth Asthana[1] the option `--revert` is
>> added to git-replay(1). This is implemented as option `--revert`, next
>> to the existing options `--advance` and `--onto`.
>>
>> The usage of these options is mutually exclusive, so the user can only
>> use one of them, and depending on which one, git-replay(1) selects a
>> "mode of operating".
>>
>> Various people have raised this behavior is somewhat confusing. In this
>> series we attempt to make the usage of git-replay(1) more intuitive and
>> user-friendly by implementing the modes as subcommands.
>
> Ok, subcommands for git-replay(1) seem like they could be a good fit
> here.
<3
>
>> This patch is submitted as an RFC to gather feedback about the design.
>> All changes are implemented as a single patch right now, and thus
>> reviewing the changes might be challenging. When we got people aligned
>> on the direction, I'll work toward cleaner patches.
>>
>> These changes are based on 'master' at 864f55e190 (The second batch,
>> 2026-02-09) with the patches of Siddharth[1] applied: 'sa/replay-revert'
>> at f79189a653 (replay: add --revert mode to reverse commit changes,
>> 2026-02-19)
>>
>> [1]: 20260218234215.89326-3-siddharthasthana31@gmail.com
>> ---
>> Documentation/git-replay.adoc | 124 ++++++++++++++++----------
>> builtin/replay.c | 150 ++++++++++++++++++++++++-------
>> replay.c | 66 +++++++-------
>> replay.h | 31 +++----
>> t/t3650-replay-basics.sh | 199 +++++++++++++++++++++++-------------------
>> 5 files changed, 349 insertions(+), 221 deletions(-)
>>
>> diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
>> index ffdf790278..a7e8dac23f 100644
>> --- a/Documentation/git-replay.adoc
>> +++ b/Documentation/git-replay.adoc
>> @@ -8,8 +8,13 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t
>>
>> SYNOPSIS
>> --------
>> -[verse]
>> -(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch> | --revert <branch>) [--ref-action[=<mode>]] <revision-range>...
>
> Do we intent to remove the experimental marker?
Yeah, I did. I don't like them in this synopsis. It seems git-replay(1)
is the only one doing this, so I'd like to get rid of it.
Doing this should end up in a separate commit.
>> +[synopsis]
>> +git replay rebase --onto <newbase> [--ref <branch>] [--contained]
>> + [--ref-action[=<mode>]] <revision-range>
>> +git replay pick --ref <branch> [--onto <newbase>]
>> + [--ref-action[=<mode>]] <revision-range>
>> +git replay revert --ref <branch> [--onto <newbase>]
>> + [--ref-action[=<mode>]] <revision-range>
>
> Subcommands with required options like this feel quite bad IMO and I'm
> not sure it makes it much more intuitive.
Okay, I did some looking up, and maybe you're right, I couldn't find any
other command that has required options. It seems all commands have some
kind of "default behavior" when no options are given.
> I guess subcommands do make it easier to convey which options pertain
> to which operation. Maybe it would be better if required arguments
> remained positional though?
I'm not sure that's better:
[synopsis]
git replay rebase <newbase> [--ref <branch>] [--contained]
[--ref-action[=<mode>]] <revision-range>
git replay pick <branch> [--onto <newbase>]
[--ref-action[=<mode>]] <revision-range>
git replay revert <branch> [--onto <newbase>]
[--ref-action[=<mode>]] <revision-range>
I don't think is better because the required argument for 'rebase' is
used differently than 'pick' and 'revert', as explained above.
I guess my main gripe with the current options is the naming: `--onto`
to rebase, `--advance` to cherry-pick, and `--revert` to revert. And
while the last one does sound intuitive, the argument to that option is
the branch you want to replay the reverted commits onto. So the argument
isn't *what* you're reverting, it's *where* you're reverting to.
With my proposal I wanted to make that more clear.
This proposal is trying to be not too disruptive (for example, for
rebase you only need to a add `rebase`), but that's maybe not a good
idea. So an alternative could be: on top of this proposal, make both
`--onto` and `--ref` required. In various cases the user will provide
the exact same argument to both options, but since git-replay(1) is a
plumbing command, we can consider this is acceptable?
And now, while writing this, I was thinking about yet another proposal.
Because --advance and --revert are pretty similar. Why is --revert not
an additional option you can add when using --advance. So instead of:
git replay --revert=my-branch master..other-branch
git replay --advance=my-branch --revert master..other-branch
@Siddharth, have you considered that?
> Also, using these subcommands appears to be required now which is a
> breaking change compared to before. The command is experimental, so this
> may be fine, but should probably be more directly mentioned.
Sure, I can do that when I clean up the commits.
--
Cheers,
Toon
next prev parent reply other threads:[~2026-03-13 16:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 19:30 [PATCH RFC] git-replay: implement subcommands Toon Claes
2026-03-11 18:33 ` Justin Tobler
2026-03-13 16:22 ` Toon Claes [this message]
2026-03-14 7:18 ` Siddharth Asthana
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87v7ezsnqf.fsf@iotcl.com \
--to=toon@iotcl.com \
--cc=chriscool@tuxfamily.org \
--cc=git@vger.kernel.org \
--cc=jltobler@gmail.com \
--cc=siddharthasthana31@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.