Git development
 help / color / mirror / Atom feed
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?

      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