From: Junio C Hamano <gitster@pobox.com>
To: Toon Claes <toon@iotcl.com>
Cc: git@vger.kernel.org, Johannes Schindelin <Johannes.Schindelin@gmx.de>
Subject: Re: [PATCH 3/3] replay: offer an option to linearize the commit topology
Date: Mon, 08 Jun 2026 12:29:07 -0700 [thread overview]
Message-ID: <xmqqtsrcvnjw.fsf@gitster.g> (raw)
In-Reply-To: <20260608-toon-git-replay-drop-merges-v1-3-e3ee71fce7b4@iotcl.com> (Toon Claes's message of "Mon, 08 Jun 2026 20:37:21 +0200")
Toon Claes <toon@iotcl.com> writes:
> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
>
> One of the stated goals of git-replay(1) is to allow implementing the
> git-rebase(1) functionality on the server side.
>
> The default mode of git-rebase(1) is to act as if `--no-rebase-merges`
> was given. This mode drops merge commits instead of replaying them, and
> linearized the commit history into a sequence of the
> regular (single-parent) commits.
"linearized" -> "linearizes"?
>
> Add option `--linearize` to git-replay(1) do the same.
"do the same" -> "to do the same"?
> Co-authored-by: Toon Claes <toon@iotcl.com>
There is no sign-off by any of the authors?
> @@ -430,12 +435,20 @@ int replay_revisions(struct rev_info *revs,
> while ((commit = get_revision(revs))) {
> const struct name_decoration *decoration;
>
> - if (commit->parents && commit->parents->next)
> + if (opts->linearize && (!commit->parents || commit->parents->next))
> + ; /* map current commit to the same as the previous commit */
This uses the same treatment on either root commits or merge
commits? If this were a mistake and this wants to handle merges but
not roots, shouldn't it be more like
if (opts->linearize && (commit->parents && commit->parents->next))
; /* map the merge to the previous */
> + else if (commit->parents && commit->parents->next)
> die(_("replaying merge commits is not supported yet!"));
And because the next one is also about merges, perhaps the early
part of this if/else if cascade can be written
if (commit->parents && commit->parents->next) {
/* We have a merge */
if (!opts->linearize)
die(_("can't replay a merge (yet)"));
; /* map current to the previous */
} else {
...
wouldn't it?
If the "map current to prev" is applicable to root, any root are
mapped to the last_commit in the above, and if we saw a root as the
first thing in the loop, last_commit is NULL, we do not do anything
here, and after the if/else if/else cascade, we see last_commit is
NULL and break out of the loop.
> + else {
> + struct commit *to_pick = reverse ? last_commit : onto;
> + last_commit =
> + pick_regular_commit(revs->repo, commit,
> + replayed_commits, to_pick,
> + &merge_opt, &result,
> + opts->linearize ? last_commit : NULL,
> + reverse, opts->empty);
> + }
>
> - last_commit = pick_regular_commit(revs->repo, commit, replayed_commits,
> - reverse ? last_commit : onto,
> - &merge_opt, &result, reverse, opts->empty);
> if (!last_commit)
> break;
> diff --git a/replay.h b/replay.h
> index 1851a07705..07e6fdcca3 100644
> --- a/replay.h
> +++ b/replay.h
> @@ -62,6 +62,11 @@ struct replay_revisions_options {
> * Defaults to REPLAY_EMPTY_COMMIT_DROP.
> */
> enum replay_empty_commit_action empty;
> +
> + /*
> + * Whether to linearize the commits (i.e. drop merge commits).
> + */
> + int linearize;
> };
>
> /* This struct is used as an out-parameter by `replay_revisions()`. */
> diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh
> index 3353bc4a4d..c781a3bb1b 100755
> --- a/t/t3650-replay-basics.sh
> +++ b/t/t3650-replay-basics.sh
> @@ -565,4 +565,26 @@ test_expect_success '--onto with --ref rejects multiple revision ranges' '
> test_grep "cannot be used with multiple revision ranges" err
> '
>
> +test_expect_success 'linearize the commit topology' '
> + test_tick &&
> + N=$(git commit-tree -m N -p L -p I L:) &&
> + N=$(git commit-tree -m N-child -p $N L:) &&
> + git update-ref refs/heads/N $N &&
> +
> + git replay --ref-action=print --linearize \
> + --onto A B..refs/heads/N >out &&
> +
> + test_line_count = 1 out &&
> + read N1 N2 N3 N4 <out &&
> +
> + cat >expect <<-EOF &&
> + * N-child
> + * I
> + * L
> + o A
> + EOF
> + git log --format=%s --graph --boundary A...$N3 >actual &&
> + test_cmp expect actual
> +'
Perhaps we would want to have a test that replays all the way down
to the root commit?
prev parent reply other threads:[~2026-06-08 19:29 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-08 18:37 [PATCH 0/3] Teach git-replay(1) to linearize merge commits Toon Claes
2026-06-08 18:37 ` [PATCH 1/3] replay: refactor enum replay_mode into a bool Toon Claes
2026-06-08 18:37 ` [PATCH 2/3] replay: add helper to put entry into mapped_commits Toon Claes
2026-06-08 18:37 ` [PATCH 3/3] replay: offer an option to linearize the commit topology Toon Claes
2026-06-08 19:29 ` Junio C Hamano [this message]
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=xmqqtsrcvnjw.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=toon@iotcl.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox