{"thread":{"id":"65282","subject":"[PATCH] replay: support replaying down from root commit","startedAt":"2026-03-17T18:57:09Z","lastAt":"2026-04-03T06:50:04Z","messageCount":17,"participants":["Toon Claes","Junio C Hamano","Christian Couder","Ben Knoble"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"539251","messageId":"20260317-toon-replay-down-to-root-v1-1-cb5c249e15fd@iotcl.com","threadId":"65282","inReplyTo":null,"subject":"[PATCH] replay: support replaying down from root commit","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-03-17T18:56:26Z","receivedAt":"2026-03-17T18:57:09Z","isPatch":true,"body":"git-replay(1) doesn't allow replaying commits all the way down to the\nroot commit. Fix that.\n\nSigned-off-by: Toon Claes <toon@iotcl.com>\n---\nThese changes might conflict Siddharth's series[1] to add '--revert' to\ngit-replay(1), although resolving that should be trivial.\n\n[1]: https://lore.kernel.org/git/20260313054035.26605-1-siddharthasthana31@gmail.com/\n---\n replay.c                 | 18 ++++++++++--------\n t/t3650-replay-basics.sh | 10 +++++++---\n 2 files changed, 17 insertions(+), 11 deletions(-)\n\ndiff --git a/replay.c b/replay.c\nindex a63f6714c4..63ff56552e 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -225,12 +225,18 @@ static struct commit *pick_regular_commit(struct repository *repo,\n \tstruct commit *base, *replayed_base;\n \tstruct tree *pickme_tree, *base_tree, *replayed_base_tree;\n \n-\tbase = pickme->parents->item;\n-\treplayed_base = mapped_commit(replayed_commits, base, onto);\n+\tif (pickme->parents) {\n+\t\tbase = pickme->parents->item;\n+\t\treplayed_base = mapped_commit(replayed_commits, base, onto);\n+\t\tbase_tree = repo_get_commit_tree(repo, base);\n+\t} else {\n+\t\tbase = NULL;\n+\t\treplayed_base = onto;\n+\t\tbase_tree = lookup_tree(repo, repo->hash_algo->empty_tree);\n+\t}\n \n \treplayed_base_tree = repo_get_commit_tree(repo, replayed_base);\n \tpickme_tree = repo_get_commit_tree(repo, pickme);\n-\tbase_tree = repo_get_commit_tree(repo, base);\n \n \tmerge_opt->branch1 = short_commit_name(repo, replayed_base);\n \tmerge_opt->branch2 = short_commit_name(repo, pickme);\n@@ -293,8 +299,6 @@ int replay_revisions(struct rev_info *revs,\n \tset_up_replay_mode(revs->repo, &revs->cmdline, opts->onto,\n \t\t\t   &detached_head, &advance, &onto, &update_refs);\n \n-\t/* FIXME: Should allow replaying commits with the first as a root commit */\n-\n \tif (prepare_revision_walk(revs) < 0) {\n \t\tret = error(_(\"error preparing revisions\"));\n \t\tgoto out;\n@@ -309,9 +313,7 @@ int replay_revisions(struct rev_info *revs,\n \t\tkhint_t pos;\n \t\tint hr;\n \n-\t\tif (!commit->parents)\n-\t\t\tdie(_(\"replaying down from root commit is not supported yet!\"));\n-\t\tif (commit->parents->next)\n+\t\tif (commit->parents && commit->parents->next)\n \t\t\tdie(_(\"replaying merge commits is not supported yet!\"));\n \n \t\tlast_commit = pick_regular_commit(revs->repo, commit, replayed_commits,\ndiff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh\nindex a03f8f9293..9c55b62757 100755\n--- a/t/t3650-replay-basics.sh\n+++ b/t/t3650-replay-basics.sh\n@@ -81,9 +81,13 @@ test_expect_success 'option --onto or --advance is mandatory' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'no base or negative ref gives no-replaying down to root error' '\n-\techo \"fatal: replaying down from root commit is not supported yet!\" >expect &&\n-\ttest_must_fail git replay --onto=topic1 topic2 2>actual &&\n+test_expect_success 'replay down to root onto another branch' '\n+\tgit replay --ref-action=print --onto main topic2 >result &&\n+\n+\ttest_line_count = 1 result &&\n+\n+\tgit log --format=%s $(cut -f 3 -d \" \" result) >actual &&\n+\ttest_write_lines E D C M L B A >expect &&\n \ttest_cmp expect actual\n '\n \n\n---\nbase-commit: ca1db8a0f7dc0dbea892e99f5b37c5fe5861be71\nchange-id: 20260317-toon-replay-down-to-root-d412048f1741\n\n"},{"id":"539256","messageId":"xmqqwlzajkha.fsf@gitster.g","threadId":"65282","inReplyTo":"20260317-toon-replay-down-to-root-v1-1-cb5c249e15fd@iotcl.com","subject":"Re: [PATCH] replay: support replaying down from root commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-17T19:59:13Z","receivedAt":"2026-03-17T19:59:15Z","isPatch":true,"body":"Toon Claes <toon@iotcl.com> writes:\n\n> git-replay(1) doesn't allow replaying commits all the way down to the\n> root commit. Fix that.\n\nOK.\n\n> -\tbase = pickme->parents->item;\n> -\treplayed_base = mapped_commit(replayed_commits, base, onto);\n> +\tif (pickme->parents) {\n> +\t\tbase = pickme->parents->item;\n> +\t\treplayed_base = mapped_commit(replayed_commits, base, onto);\n> +\t\tbase_tree = repo_get_commit_tree(repo, base);\n\nSo, if we are replaying a commit with parent(s), we do the same as\nbefore (base_tree used to be computed a bit later).  But ...\n\n> +\t} else {\n> +\t\tbase = NULL;\n> +\t\treplayed_base = onto;\n> +\t\tbase_tree = lookup_tree(repo, repo->hash_algo->empty_tree);\n> +\t}\n\n... if we are replaying the root commit, there is no base (in\ncontrast to \"the first parent of the original commit\" used in the\nother branch of this if-else construct).  We use an empty tree for\nthe base_tree, which is the natural thing to use to replay for a\nroot commit, of course.\n\nI am not sure why replayed_base is computed differently, though?  Is\nit because mapped_commit() would not work when base==NULL?\n\nI have to wonder if the handling of that case should also be\nencapsulated inside mapped_commit() helper, just like the helper\nknows to \"fallback\" when the commit is not yet mapped, but that is\nminor.  After all, if we drive that line of thought to the extreme,\nwe would end up making repo_get_commit_tree() to return an empty\ntree object for base==NULL, too, which may be logical but it is\nprobably too much.\n\n"},{"id":"539860","messageId":"87qzp916o6.fsf@iotcl.com","threadId":"65282","inReplyTo":"xmqqwlzajkha.fsf@gitster.g","subject":"Re: [PATCH] replay: support replaying down from root commit","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-03-24T17:25:13Z","receivedAt":"2026-03-24T17:25:19Z","isPatch":true,"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Toon Claes <toon@iotcl.com> writes:\n>\n>> git-replay(1) doesn't allow replaying commits all the way down to the\n>> root commit. Fix that.\n>\n> OK.\n>\n>> -\tbase = pickme->parents->item;\n>> -\treplayed_base = mapped_commit(replayed_commits, base, onto);\n>> +\tif (pickme->parents) {\n>> +\t\tbase = pickme->parents->item;\n>> +\t\treplayed_base = mapped_commit(replayed_commits, base, onto);\n>> +\t\tbase_tree = repo_get_commit_tree(repo, base);\n>\n> So, if we are replaying a commit with parent(s), we do the same as\n> before (base_tree used to be computed a bit later).  But ...\n>\n>> +\t} else {\n>> +\t\tbase = NULL;\n>> +\t\treplayed_base = onto;\n>> +\t\tbase_tree = lookup_tree(repo, repo->hash_algo->empty_tree);\n>> +\t}\n>\n> ... if we are replaying the root commit, there is no base (in\n> contrast to \"the first parent of the original commit\" used in the\n> other branch of this if-else construct).  We use an empty tree for\n> the base_tree, which is the natural thing to use to replay for a\n> root commit, of course.\n>\n> I am not sure why replayed_base is computed differently, though?  Is\n> it because mapped_commit() would not work when base==NULL?\n\nThat's correct, mapped_commit() dereferences commit->object.oid.\n\n> I have to wonder if the handling of that case should also be\n> encapsulated inside mapped_commit() helper, just like the helper\n> knows to \"fallback\" when the commit is not yet mapped\n\nI'm fine either way, so I'll do that in v2.\n\n> After all, if we drive that line of thought to the extreme, we would\n> end up making repo_get_commit_tree() to return an empty tree object\n> for base==NULL, too, which may be logical but it is probably too much.\n\nWell, it's a bit annoying `struct commit::parents` is a `struct\ncommit_list`, so we have to first check that pointer before we can\ndereference `item`, so that guard do we need anyway. So I agree it's too\nmuch.\n\nOne other thing, in v2 I'm also fixing the merge ancestor label. For\nroot commits it will say \"empty tree\" instead of \"parent of <commit>\",\nso conflict messages aren't misleading.\n\n-- \nCheers,\nToon\n"},{"id":"539877","messageId":"20260324-toon-replay-down-to-root-v2-1-34e723489f6e@iotcl.com","threadId":"65282","inReplyTo":"20260317-toon-replay-down-to-root-v1-1-cb5c249e15fd@iotcl.com","subject":"[PATCH v2] replay: support replaying down from root commit","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-03-24T19:35:41Z","receivedAt":"2026-03-24T19:35:54Z","isPatch":true,"body":"git-replay(1) doesn't allow replaying commits all the way down to the\nroot commit. Fix that.\n\nSigned-off-by: Toon Claes <toon@iotcl.com>\n---\nThese changes might conflict Siddharth's series[1] to add '--revert' to\ngit-replay(1), although resolving that should be trivial.\n\n[1]: https://lore.kernel.org/git/20260313054035.26605-1-siddharthasthana31@gmail.com/\n---\nChanges in v2:\n- Add NULL pointer check for `commit` in mapped_commit().\n- Change ancestor message to \"empty tree\" when replaying root commit.\n- Link to v1: https://patch.msgid.link/20260317-toon-replay-down-to-root-v1-1-cb5c249e15fd@iotcl.com\n---\n replay.c                 | 27 +++++++++++++++++----------\n t/t3650-replay-basics.sh | 10 +++++++---\n 2 files changed, 24 insertions(+), 13 deletions(-)\n\ndiff --git a/replay.c b/replay.c\nindex a63f6714c4..92f2279156 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -209,7 +209,10 @@ static struct commit *mapped_commit(kh_oid_map_t *replayed_commits,\n \t\t\t\t    struct commit *commit,\n \t\t\t\t    struct commit *fallback)\n {\n-\tkhint_t pos = kh_get_oid_map(replayed_commits, commit->object.oid);\n+\tkhint_t pos;\n+\tif (!commit)\n+\t\treturn fallback;\n+\tpos = kh_get_oid_map(replayed_commits, commit->object.oid);\n \tif (pos == kh_end(replayed_commits))\n \t\treturn fallback;\n \treturn kh_value(replayed_commits, pos);\n@@ -225,16 +228,24 @@ static struct commit *pick_regular_commit(struct repository *repo,\n \tstruct commit *base, *replayed_base;\n \tstruct tree *pickme_tree, *base_tree, *replayed_base_tree;\n \n-\tbase = pickme->parents->item;\n-\treplayed_base = mapped_commit(replayed_commits, base, onto);\n+\tif (pickme->parents) {\n+\t\tbase = pickme->parents->item;\n+\t\tbase_tree = repo_get_commit_tree(repo, base);\n+\t} else {\n+\t\tbase = NULL;\n+\t\tbase_tree = lookup_tree(repo, repo->hash_algo->empty_tree);\n+\t}\n \n+\treplayed_base = mapped_commit(replayed_commits, base, onto);\n \treplayed_base_tree = repo_get_commit_tree(repo, replayed_base);\n \tpickme_tree = repo_get_commit_tree(repo, pickme);\n-\tbase_tree = repo_get_commit_tree(repo, base);\n \n \tmerge_opt->branch1 = short_commit_name(repo, replayed_base);\n \tmerge_opt->branch2 = short_commit_name(repo, pickme);\n-\tmerge_opt->ancestor = xstrfmt(\"parent of %s\", merge_opt->branch2);\n+\tif (pickme->parents)\n+\t\tmerge_opt->ancestor = xstrfmt(\"parent of %s\", merge_opt->branch2);\n+\telse\n+\t\tmerge_opt->ancestor = xstrdup(\"empty tree\");\n \n \tmerge_incore_nonrecursive(merge_opt,\n \t\t\t\t  base_tree,\n@@ -293,8 +304,6 @@ int replay_revisions(struct rev_info *revs,\n \tset_up_replay_mode(revs->repo, &revs->cmdline, opts->onto,\n \t\t\t   &detached_head, &advance, &onto, &update_refs);\n \n-\t/* FIXME: Should allow replaying commits with the first as a root commit */\n-\n \tif (prepare_revision_walk(revs) < 0) {\n \t\tret = error(_(\"error preparing revisions\"));\n \t\tgoto out;\n@@ -309,9 +318,7 @@ int replay_revisions(struct rev_info *revs,\n \t\tkhint_t pos;\n \t\tint hr;\n \n-\t\tif (!commit->parents)\n-\t\t\tdie(_(\"replaying down from root commit is not supported yet!\"));\n-\t\tif (commit->parents->next)\n+\t\tif (commit->parents && commit->parents->next)\n \t\t\tdie(_(\"replaying merge commits is not supported yet!\"));\n \n \t\tlast_commit = pick_regular_commit(revs->repo, commit, replayed_commits,\ndiff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh\nindex a03f8f9293..9c55b62757 100755\n--- a/t/t3650-replay-basics.sh\n+++ b/t/t3650-replay-basics.sh\n@@ -81,9 +81,13 @@ test_expect_success 'option --onto or --advance is mandatory' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'no base or negative ref gives no-replaying down to root error' '\n-\techo \"fatal: replaying down from root commit is not supported yet!\" >expect &&\n-\ttest_must_fail git replay --onto=topic1 topic2 2>actual &&\n+test_expect_success 'replay down to root onto another branch' '\n+\tgit replay --ref-action=print --onto main topic2 >result &&\n+\n+\ttest_line_count = 1 result &&\n+\n+\tgit log --format=%s $(cut -f 3 -d \" \" result) >actual &&\n+\ttest_write_lines E D C M L B A >expect &&\n \ttest_cmp expect actual\n '\n \n\n---\nbase-commit: ca1db8a0f7dc0dbea892e99f5b37c5fe5861be71\nchange-id: 20260317-toon-replay-down-to-root-d412048f1741\n\n"},{"id":"539879","messageId":"xmqqtsu5xaw0.fsf@gitster.g","threadId":"65282","inReplyTo":"20260324-toon-replay-down-to-root-v2-1-34e723489f6e@iotcl.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-24T19:53:03Z","receivedAt":"2026-03-24T19:53:05Z","isPatch":true,"body":"Toon Claes <toon@iotcl.com> writes:\n\n> git-replay(1) doesn't allow replaying commits all the way down to the\n> root commit. Fix that.\n>\n> Signed-off-by: Toon Claes <toon@iotcl.com>\n> ---\n> These changes might conflict Siddharth's series[1] to add '--revert' to\n> git-replay(1), although resolving that should be trivial.\n\nTrue.  This round looks great to me.  Will queue.\n\nShall we mark the topic for 'next' now?\n\nThanks.\n"},{"id":"539922","messageId":"CAP8UFD1zJXnsm7POK32GqEu4xSC+VO5mfzUpM-jn+Nr1qvzEFQ@mail.gmail.com","threadId":"65282","inReplyTo":"xmqqtsu5xaw0.fsf@gitster.g","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2026-03-25T10:00:18Z","receivedAt":"2026-03-25T10:00:32Z","isPatch":true,"body":"On Tue, Mar 24, 2026 at 8:56 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Toon Claes <toon@iotcl.com> writes:\n>\n> > git-replay(1) doesn't allow replaying commits all the way down to the\n> > root commit. Fix that.\n> >\n> > Signed-off-by: Toon Claes <toon@iotcl.com>\n> > ---\n> > These changes might conflict Siddharth's series[1] to add '--revert' to\n> > git-replay(1), although resolving that should be trivial.\n>\n> True.  This round looks great to me.  Will queue.\n>\n> Shall we mark the topic for 'next' now?\n\nThe patch looks good to me, but I wonder if the docs should be updated\nsomehow, especially to try to avoid confusion in case users don't\nproperly specify a range.\n\nFor example, before this, `git replay --onto main topic` would fail,\nbut emit \"fatal: replaying down from root commit is not supported\nyet!\". This would likely help users understand that they might need to\nproperly specify a range like \"main..topic\" instead of 'topic\".\n\nNow it would likely fail without any error message.\n\nMaybe something like the following could help:\n\n--- a/Documentation/git-replay.adoc\n+++ b/Documentation/git-replay.adoc\n@@ -23,6 +23,10 @@ instead get update commands that can be piped to\n`git update-ref --stdin`\n\n THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n\n+Note that `git replay --onto main topic` replays the topic branch starting\n+from the root commit, not from main. What you might want instead is\n+`git replay --onto main main..topic`.\n+\n OPTIONS\n -------\n\n?\n\nAnd yeah currently `git replay` is a plumbing command that most\nregular users shouldn't likely use, but I think Elijah's goal was to\neventually make it user friendly enough for advanced users with\nstacked branches.\n"},{"id":"539934","messageId":"E0A14573-BBE2-4ADF-989C-E5B2A7E3E166@gmail.com","threadId":"65282","inReplyTo":"CAP8UFD1zJXnsm7POK32GqEu4xSC+VO5mfzUpM-jn+Nr1qvzEFQ@mail.gmail.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-03-25T12:19:49Z","receivedAt":"2026-03-25T12:20:01Z","isPatch":true,"body":"\n> Le 25 mars 2026 à 06:05, Christian Couder <christian.couder@gmail.com> a écrit :\n> \n> ﻿On Tue, Mar 24, 2026 at 8:56 PM Junio C Hamano <gitster@pobox.com> wrote:\n>> \n>> Toon Claes <toon@iotcl.com> writes:\n>> \n>>> git-replay(1) doesn't allow replaying commits all the way down to the\n>>> root commit. Fix that.\n>>> \n>>> Signed-off-by: Toon Claes <toon@iotcl.com>\n>>> ---\n>>> These changes might conflict Siddharth's series[1] to add '--revert' to\n>>> git-replay(1), although resolving that should be trivial.\n>> \n>> True.  This round looks great to me.  Will queue.\n>> \n>> Shall we mark the topic for 'next' now?\n> \n> The patch looks good to me, but I wonder if the docs should be updated\n> somehow, especially to try to avoid confusion in case users don't\n> properly specify a range.\n> \n> For example, before this, `git replay --onto main topic` would fail,\n> but emit \"fatal: replaying down from root commit is not supported\n> yet!\". This would likely help users understand that they might need to\n> properly specify a range like \"main..topic\" instead of 'topic\".\n> \n> Now it would likely fail without any error message.\n\nHaving used replay in a large monorepo where I juggle many branches (so rebasing another in-flight topic without otherwise interrupting my work is valuable), I’ve made this mistake a few times. Some way of handling it more gracefully would be appreciated: perhaps the root case is rare enough to warrant an option or confirmation prompt (when attached interactively)?\n\n> \n> Maybe something like the following could help:\n> \n> --- a/Documentation/git-replay.adoc\n> +++ b/Documentation/git-replay.adoc\n> @@ -23,6 +23,10 @@ instead get update commands that can be piped to\n> `git update-ref --stdin`\n> \n> THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n> \n> +Note that `git replay --onto main topic` replays the topic branch starting\n> +from the root commit, not from main. What you might want instead is\n> +`git replay --onto main main..topic`.\n> +\n> OPTIONS\n> -------\n> \n> ?\n> \n> And yeah currently `git replay` is a plumbing command that most\n> regular users shouldn't likely use, but I think Elijah's goal was to\n> eventually make it user friendly enough for advanced users with\n> stacked branches.\n> \n"},{"id":"539942","messageId":"87a4vv2ada.fsf@iotcl.com","threadId":"65282","inReplyTo":"CAP8UFD1zJXnsm7POK32GqEu4xSC+VO5mfzUpM-jn+Nr1qvzEFQ@mail.gmail.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-03-25T15:32:17Z","receivedAt":"2026-03-25T15:32:24Z","isPatch":true,"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n> On Tue, Mar 24, 2026 at 8:56 PM Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>> Toon Claes <toon@iotcl.com> writes:\n>>\n>> > git-replay(1) doesn't allow replaying commits all the way down to the\n>> > root commit. Fix that.\n>> >\n>> > Signed-off-by: Toon Claes <toon@iotcl.com>\n>> > ---\n>> > These changes might conflict Siddharth's series[1] to add '--revert' to\n>> > git-replay(1), although resolving that should be trivial.\n>>\n>> True.  This round looks great to me.  Will queue.\n>>\n>> Shall we mark the topic for 'next' now?\n>\n> The patch looks good to me, but I wonder if the docs should be updated\n> somehow, especially to try to avoid confusion in case users don't\n> properly specify a range.\n>\n> For example, before this, `git replay --onto main topic` would fail,\n> but emit \"fatal: replaying down from root commit is not supported\n> yet!\".\n\nI'm fixing that in a separate series.\n\n> This would likely help users understand that they might need to\n> properly specify a range like \"main..topic\" instead of 'topic\".\n>\n> Now it would likely fail without any error message.\n>\n> Maybe something like the following could help:\n>\n> --- a/Documentation/git-replay.adoc\n> +++ b/Documentation/git-replay.adoc\n> @@ -23,6 +23,10 @@ instead get update commands that can be piped to\n> `git update-ref --stdin`\n>\n>  THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n>\n> +Note that `git replay --onto main topic` replays the topic branch starting\n> +from the root commit, not from main. What you might want instead is\n> +`git replay --onto main main..topic`.\n> +\n\nDefinitely would help, not sure it needs to be part of this series.\n\n-- \nCheers,\nToon\n"},{"id":"539943","messageId":"875x6j2a7v.fsf@iotcl.com","threadId":"65282","inReplyTo":"E0A14573-BBE2-4ADF-989C-E5B2A7E3E166@gmail.com","subject":"Re: Make git-replay(1) warn if revision-range isn't a range (was: Re: [PATCH v2] replay: support replaying down from root commit)","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-03-25T15:35:32Z","receivedAt":"2026-03-25T15:35:39Z","isPatch":true,"body":"Ben Knoble <ben.knoble@gmail.com> writes:\n\n>> The patch looks good to me, but I wonder if the docs should be updated\n>> somehow, especially to try to avoid confusion in case users don't\n>> properly specify a range.\n>> \n>> For example, before this, `git replay --onto main topic` would fail,\n>> but emit \"fatal: replaying down from root commit is not supported\n>> yet!\". This would likely help users understand that they might need to\n>> properly specify a range like \"main..topic\" instead of 'topic\".\n>> \n>> Now it would likely fail without any error message.\n>\n> Having used replay in a large monorepo where I juggle many branches\n> (so rebasing another in-flight topic without otherwise interrupting my\n> work is valuable), I’ve made this mistake a few times. Some way of\n> handling it more gracefully would be appreciated: perhaps the root\n> case is rare enough to warrant an option or confirmation prompt (when\n> attached interactively)?\n\nYeah, there is definetily room for improvement here. But I consider that\noutside the scope of this series and more like #leftoverbits.\n\n-- \nCheers,\nToon\n"},{"id":"539945","messageId":"87341n2a4w.fsf@iotcl.com","threadId":"65282","inReplyTo":"87a4vv2ada.fsf@iotcl.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-03-25T15:37:19Z","receivedAt":"2026-03-25T15:37:26Z","isPatch":true,"body":"Toon Claes <toon@iotcl.com> writes:\n\n> I'm fixing that in a separate series.\n\nLOL, whoops I'm mixing up my own series. Sorry about that.\n\n-- \nCheers,\nToon\n"},{"id":"539962","messageId":"xmqq7bqzx3au.fsf@gitster.g","threadId":"65282","inReplyTo":"CAP8UFD1zJXnsm7POK32GqEu4xSC+VO5mfzUpM-jn+Nr1qvzEFQ@mail.gmail.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-25T16:49:13Z","receivedAt":"2026-03-25T16:49:16Z","isPatch":true,"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n> For example, before this, `git replay --onto main topic` would fail,\n> but emit \"fatal: replaying down from root commit is not supported\n> yet!\". This would likely help users understand that they might need to\n> properly specify a range like \"main..topic\" instead of 'topic\".\n>\n> Now it would likely fail without any error message.\n\nThe fact that I do not quite understand the suggested change is a\nvery strong sign that people would be helped by a bit more\ndocumentation ;-).\n\nDepending on what is in \"topic\" and what \"main\" has, wouldn't it be\npossible that the history leads to \"topic\" replay cleanly on top of\n\"main\"?  And if there are problems (e.g., the replayed history may\nwant to add a file where \"main\"'s history already has contents with\na different ancestry sitting there, or the path may be taken by a\ndirectory), wouldn't \"git replay\" fail loudly explaining what got\nconflicted, instead of failing silently?\n\n> Maybe something like the following could help:\n>\n> --- a/Documentation/git-replay.adoc\n> +++ b/Documentation/git-replay.adoc\n> @@ -23,6 +23,10 @@ instead get update commands that can be piped to\n> `git update-ref --stdin`\n>\n>  THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n>\n> +Note that `git replay --onto main topic` replays the topic branch starting\n> +from the root commit, not from main. What you might want instead is\n> +`git replay --onto main main..topic`.\n\nTo be helpful, \"might want\" needs to be accompanied by \"if you want\nto do X\", I think.  In this case, that X probably is \"recreate what\nwas done on 'topic' since it forked from 'main' on top of 'main'\".\n\nThanks.\n"},{"id":"540200","messageId":"xmqqfr5lkyq8.fsf@gitster.g","threadId":"65282","inReplyTo":"87a4vv2ada.fsf@iotcl.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-27T16:45:35Z","receivedAt":"2026-03-27T16:45:38Z","isPatch":true,"body":"Toon Claes <toon@iotcl.com> writes:\n\n>> Maybe something like the following could help:\n>>\n>> --- a/Documentation/git-replay.adoc\n>> +++ b/Documentation/git-replay.adoc\n>> @@ -23,6 +23,10 @@ instead get update commands that can be piped to\n>> `git update-ref --stdin`\n>>\n>>  THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n>>\n>> +Note that `git replay --onto main topic` replays the topic branch starting\n>> +from the root commit, not from main. What you might want instead is\n>> +`git replay --onto main main..topic`.\n>> +\n>\n> Definitely would help, not sure it needs to be part of this series.\n\nWhere else should the patch to add such a note to the documentation\ngo, though?  Without this patch, we do not is because the command\nwill not take such a command line.  With this patch that adds the\n\"now we allow replay to take a single tip commit and replay the\nhistory leading to the tip all the way down to root\" feature, the\nnote may become relevant.\n\nSo to me, it looks like it is either we will never add such a note\nbecause it is irrelevant and everybody should know the consequence\nof passing \"topic\", not \"main..topic\", or we will have to add such a\nnote as part of the series (if the note would help the readers).\n\nEven though I am on the fence about the need for this specific note\nin the documentation, it does not make sense to me to say \"this will\nhelp but we are not doing so here\".\n\nMy comment on \"might\" in \"What you might\" in the thread still\napplies, by the way.\n\nThanks.\n"},{"id":"540501","messageId":"CAP8UFD3P2Gs0J1FNyKW2URwSEW4ZaTrVO7cM1V8sG+zzXctbhg@mail.gmail.com","threadId":"65282","inReplyTo":"xmqqfr5lkyq8.fsf@gitster.g","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2026-03-31T10:34:19Z","receivedAt":"2026-03-31T10:34:32Z","isPatch":true,"body":"On Fri, Mar 27, 2026 at 5:45 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Toon Claes <toon@iotcl.com> writes:\n>\n> >> Maybe something like the following could help:\n> >>\n> >> --- a/Documentation/git-replay.adoc\n> >> +++ b/Documentation/git-replay.adoc\n> >> @@ -23,6 +23,10 @@ instead get update commands that can be piped to\n> >> `git update-ref --stdin`\n> >>\n> >>  THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n> >>\n> >> +Note that `git replay --onto main topic` replays the topic branch starting\n> >> +from the root commit, not from main. What you might want instead is\n> >> +`git replay --onto main main..topic`.\n> >> +\n> >\n> > Definitely would help, not sure it needs to be part of this series.\n>\n> Where else should the patch to add such a note to the documentation\n> go, though?  Without this patch, we do not is because the command\n> will not take such a command line.  With this patch that adds the\n> \"now we allow replay to take a single tip commit and replay the\n> history leading to the tip all the way down to root\" feature, the\n> note may become relevant.\n>\n> So to me, it looks like it is either we will never add such a note\n> because it is irrelevant and everybody should know the consequence\n> of passing \"topic\", not \"main..topic\", or we will have to add such a\n> note as part of the series (if the note would help the readers).\n>\n> Even though I am on the fence about the need for this specific note\n> in the documentation, it does not make sense to me to say \"this will\n> help but we are not doing so here\".\n>\n> My comment on \"might\" in \"What you might\" in the thread still\n> applies, by the way.\n\nAnother approach with this is to consider that in the first place the\nmain issue is that `git replay` doesn't emit any error message when it\nfails due to a conflict, which isn't user friendly.\n\nSo if we are about to fix that main issue in a separate patch or\nseries, and if we plan to emit something like the following in the\nregular case:\n\n\"fatal: replaying failed due to conflict\"\n\nand something like the following when replaying from a root commit:\n\n\"fatal: replaying from root commit XXX failed due to conflict\"\n\nthen I think it would alleviate the need for a doc update.\n\nBut anyway even if we are planning such an error message fix, I think\na doc update would be nice, either along with such an error message\nfix or along with this patch which allows replaying from a root\ncommit.\n"},{"id":"540534","messageId":"xmqq4ilw2cnw.fsf@gitster.g","threadId":"65282","inReplyTo":"CAP8UFD3P2Gs0J1FNyKW2URwSEW4ZaTrVO7cM1V8sG+zzXctbhg@mail.gmail.com","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-31T16:20:51Z","receivedAt":"2026-03-31T16:20:54Z","isPatch":true,"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n> So if we are about to fix that main issue in a separate patch or\n> series, and if we plan to emit something like the following in the\n> regular case:\n>\n> \"fatal: replaying failed due to conflict\"\n>\n> and something like the following when replaying from a root commit:\n>\n> \"fatal: replaying from root commit XXX failed due to conflict\"\n>\n> then I think it would alleviate the need for a doc update.\n\nHmph, what would you do to the other side (i.e., replay from some\nspecified boundary) of the message?  When the version of \"git\nreplay\" command a user who sees for the first time comes with the\nability to replay from a root on day one, \"from root commit\" is not\nso special from \"from these boundary commits\", so I am not sure if\nit makes sense to have such a message that treats the down-to-root\ncase any specially.\n\n\n"},{"id":"540740","messageId":"87zf3ld90k.fsf@toon--20250203-5JQV3.mail-host-address-is-not-set","threadId":"65282","inReplyTo":"xmqq4ilw2cnw.fsf@gitster.g","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2026-04-02T09:08:43Z","receivedAt":"2026-04-02T09:08:55Z","isPatch":true,"body":"\nJunio C Hamano <gitster@pobox.com> writes:\n\n> Toon Claes <toon@iotcl.com> writes:\n>\n>>> Maybe something like the following could help:\n>>>\n>>> --- a/Documentation/git-replay.adoc\n>>> +++ b/Documentation/git-replay.adoc\n>>> @@ -23,6 +23,10 @@ instead get update commands that can be piped to\n>>> `git update-ref --stdin`\n>>>\n>>>  THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.\n>>>\n>>> +Note that `git replay --onto main topic` replays the topic branch starting\n>>> +from the root commit, not from main. What you might want instead is\n>>> +`git replay --onto main main..topic`.\n>>> +\n>>\n>> Definitely would help, not sure it needs to be part of this series.\n>\n> Where else should the patch to add such a note to the documentation\n> go, though?\n\nFirst let me clarify, I'm sorry but I posted that message because I was\nmessing up two of my patch series. Yes, that change (if made) should\nbelong to this series.\n\n> Where else should the patch to add such a note to the documentation\n> go, though?  Without this patch, we do not is because the command\n> will not take such a command line.  With this patch that adds the\n> \"now we allow replay to take a single tip commit and replay the\n> history leading to the tip all the way down to root\" feature, the\n> note may become relevant.\n>\n> So to me, it looks like it is either we will never add such a note\n> because it is irrelevant and everybody should know the consequence\n> of passing \"topic\", not \"main..topic\", or we will have to add such a\n> note as part of the series (if the note would help the readers).\n>\n> Even though I am on the fence about the need for this specific note\n> in the documentation, it does not make sense to me to say \"this will\n> help but we are not doing so here\".\n\nThe git-replay(1) docs refer to \"Specifying Ranges\" in\ngit-rev-parse(1). The section itself is included from\nDocumentation/revisions.adoc. If I look at \"Revision Range Summary\":\n\n    Revision Range Summary\n    ----------------------\n    '<rev>'::\n    \tInclude commits that are reachable from <rev> (i.e. <rev> and\n    \tits ancestors).\n\nPersonally I would say that's clear enough, and it feels a redundant to\nrepeat ourselves in the git-replay(1) docs. It's basically the same as\nfor every other command (git-log(1) for example).\n\nNow I can understand it can be confusing when you compare this to how\ngit-rebase(1) works. But if you ask me, using git-rebase(1) with\n'--onto' is a bit awkward anyway.\n\nNevertheless, looking at what the git-replay(1) docs now say about the\n'<revision-range>':\n\n    <revision-range>::\n    \tRange of commits to replay; see \"Specifying Ranges\" in\n    \tlinkgit:git-rev-parse[1]. In `--advance <branch>` mode, the\n    \trange should have a single tip, so that it's clear to which tip the\n    \tadvanced <branch> should point. Any commits in the range whose\n    \tchanges are already present in the branch the commits are being\n    \treplayed onto will be dropped.\n\nThe phrasing around dropping commits can cause confusion. We should say\ninstead empty commits are dropped.\n\nOne other thing to note though, in my other patch series I'm changing\nthe docs to use stuck form. I think that also helps to clarify the\nargument to '--onto' isn't part of the revision range.\n\nBut to summarize: I'm not sure a documentation change is needed, but if\nyou insist, I'm attaching a fixup patch (it's based on\nsa/replay-revert). I'm leaving it to Christian an Junio to decide\nwhether it should be included. I'm happy to take it to a separate series\nif you consider that a better idea.\n\n> Christian Couder <christian.couder@gmail.com> writes:\n>\n>> So if we are about to fix that main issue in a separate patch or\n>> series, and if we plan to emit something like the following in the\n>> regular case:\n>>\n>> \"fatal: replaying failed due to conflict\"\n>>\n>> and something like the following when replaying from a root commit:\n>>\n>> \"fatal: replaying from root commit XXX failed due to conflict\"\n>>\n>> then I think it would alleviate the need for a doc update.\n>\n> Hmph, what would you do to the other side (i.e., replay from some\n> specified boundary) of the message?  When the version of \"git\n> replay\" command a user who sees for the first time comes with the\n> ability to replay from a root on day one, \"from root commit\" is not\n> so special from \"from these boundary commits\", so I am not sure if\n> it makes sense to have such a message that treats the down-to-root\n> case any specially.\n\nI agree, making a separate error message for when replaying down to root\nseems a bit of an overkill.\n\n\nCheers, Toon\n\n---\n\nFrom: Toon Claes <toon@iotcl.com>\nDate: Thu, 2 Apr 2026 10:52:59 +0200\nSubject: [PATCH] fixup! Add support to git-replay down from root commit\n\n---\n Documentation/git-replay.adoc | 16 +++++++++-------\n 1 file changed, 9 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc\nindex 997097e420..fb73a57444 100644\n--- a/Documentation/git-replay.adoc\n+++ b/Documentation/git-replay.adoc\n@@ -78,13 +78,15 @@ incompatible with `--contained` (which is a modifier for `--onto` only).\n The default mode can be configured via the `replay.refAction` configuration variable.\n \n <revision-range>::\n-\tRange of commits to replay; see \"Specifying Ranges\" in\n-\tlinkgit:git-rev-parse[1]. In `--advance <branch>` or\n-\t`--revert <branch>` mode, the range should have a single tip,\n-\tso that it's clear to which tip the advanced or reverted\n-\t<branch> should point. Any commits in the range whose changes\n-\tare already present in the branch the commits are being\n-\treplayed onto will be dropped.\n+\tEach ref specified in the `<revision-range>` is replayed and updated\n+\tseparately. All commits reachable from those refs are replayed and thus\n+\tif no dotted range notation is used or excluded revision is given, each\n+\tref is replayed down to root.\n+\tCommits that end up being empty are dropped.\n+\tOnly one positive ref is allowed when using `--advance <branch>` or\n+\t`--revert <branch>`.\n+\tConsult \"Specifying Ranges\" in linkgit:git-rev-parse[1] for more\n+\tinformation.\n \n :git-replay: 1\n include::rev-list-options.adoc[]\n-- \n2.53.0.310.g728cabbaf7\n\n"},{"id":"540776","messageId":"xmqqv7e9qorx.fsf@gitster.g","threadId":"65282","inReplyTo":"87zf3ld90k.fsf@toon--20250203-5JQV3.mail-host-address-is-not-set","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-04-02T17:02:10Z","receivedAt":"2026-04-02T17:02:13Z","isPatch":true,"body":"Toon Claes <toon@iotcl.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n> ...\n>> Even though I am on the fence about the need for this specific note\n>> in the documentation, ...\n> ...\n> But to summarize: I'm not sure a documentation change is needed, but if\n> you insist, I'm attaching a fixup patch (it's based on\n> sa/replay-revert). I'm leaving it to Christian an Junio to decide\n> whether it should be included. I'm happy to take it to a separate series\n> if you consider that a better idea.\n\nAs I already said, I am not enthusiastic about the \"how about adding\nsomething like this\" Christian gave us and I think we can do without\nit, so I'll leave it up to Christian ;-)\n\nThanks, all.\n"},{"id":"540834","messageId":"CAP8UFD1N0QHTVhG=FtFV2TbiLPBq5bUPds8=TqR4Rq7kziXg2w@mail.gmail.com","threadId":"65282","inReplyTo":"xmqqv7e9qorx.fsf@gitster.g","subject":"Re: [PATCH v2] replay: support replaying down from root commit","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2026-04-03T06:49:52Z","receivedAt":"2026-04-03T06:50:04Z","isPatch":true,"body":"On Thu, Apr 2, 2026 at 7:02 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Toon Claes <toon@iotcl.com> writes:\n>\n> > Junio C Hamano <gitster@pobox.com> writes:\n> > ...\n> >> Even though I am on the fence about the need for this specific note\n> >> in the documentation, ...\n> > ...\n> > But to summarize: I'm not sure a documentation change is needed, but if\n> > you insist, I'm attaching a fixup patch (it's based on\n> > sa/replay-revert). I'm leaving it to Christian an Junio to decide\n> > whether it should be included. I'm happy to take it to a separate series\n> > if you consider that a better idea.\n>\n> As I already said, I am not enthusiastic about the \"how about adding\n> something like this\" Christian gave us and I think we can do without\n> it, so I'll leave it up to Christian ;-)\n\nLet's do without it then. We can take care of this when we eventually\ndecide to emit error messages when `git replay` fails, which can be\naddressed as a separate issue.\n"}]}