Subject: [PATCH 1/2] replay: die descriptively when invalid commit-ish

From: [email-masked]
Date: Mon, 22 Dec 2025 23:04:42 +0100

From: Kristoffer Haugsbakk <[email-masked]>

Giving an invalid commit-ish to `--onto` or `--advance` makes
git-replay(1) fail with:

    fatal: Replaying down to root commit is not supported yet!

Going backwards from this point:

1. `onto` is `NULL` from `determine_replay_mode`;
2. that function in turn calls `peel_committish`; and
3. here we return `NULL` if `repo_get_oid` fails.

Let’s die immediately with a descriptive error message instead.

Doing this also provides us with a descriptive error if we “forget” to
provide an argument to `--onto` (but we really do unintentionally):[1]

    $ git replay --onto ^main topic1
    fatal: '^main' is not a valid commit-ish

† 1: The argument to `--onto` is mandatory and the option parser accepts
     both `--onto=<name>` (stuck form) and `--onto name`. The latter
     form makes it easy to unintentionally pass something to the option
     when you really meant to pass a positional argument.

Signed-off-by: Kristoffer Haugsbakk <[email-masked]>
---
 builtin/replay.c         |  2 +-
 t/t3650-replay-basics.sh | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/builtin/replay.c b/builtin/replay.c
index 6172c8aacc9..175b64c5335 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -33,7 +33,7 @@ static struct commit *peel_committish(struct repository *repo, const char *name)
 	struct object_id oid;
 
 	if (repo_get_oid(repo, name, &oid))
-		return NULL;
+		die(_("'%s' is not a valid commit-ish"), name);
 	obj = parse_object(repo, &oid);
 	return (struct commit *)repo_peel_to_type(repo, name, 0, obj,
 						  OBJ_COMMIT);
diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh
index 58b37599357..bfe8e01da49 100755
--- a/t/t3650-replay-basics.sh
+++ b/t/t3650-replay-basics.sh
@@ -51,6 +51,22 @@ test_expect_success 'setup bare' '
 	git clone --bare . bare
 '
 
+test_expect_success '--onto with invalid commit-ish' '
+	cat >expect <<-EOF &&
+	fatal: ${SQ}refs/not-valid${SQ} is not a valid commit-ish
+	EOF
+	test_must_fail git replay --onto=refs/not-valid topic1..topic2 2>actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--advance with invalid commit-ish' '
+	cat >expect <<-EOF &&
+	fatal: ${SQ}refs/not-valid${SQ} is not a valid commit-ish
+	EOF
+	test_must_fail git replay --advance=refs/not-valid topic1..topic2 2>actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'using replay to rebase two branches, one on top of other' '
 	git replay --onto main topic1..topic2 >result &&
 
-- 
2.52.0.10.g08704017180