[PATCH v10 3.3/3.7] fixup! history: add squash subcommand to fold a range

Phillip Wood <[email protected]> Mon, 3 Aug 2026 10:49:23 +0100
Newsgroups org.kernel.vger.git
Message-ID <9513165effed465acb633eb0152f98dd870b7bf2.1785750108.git.phillip.wood@dunelm.org.uk>
From: Phillip Wood <[email protected]>

reject root commits

We do not support squashing down to the root commit yet (we should
probably require explicit confirmation if we ever do support it to avoid
nasty surprises) so error out if we see a commit with no parents. As
explained in the test, because we use --ancestry-path it is not
straight forward to trick it into walking back to the root commit.
---
 builtin/history.c         |  4 ++++
 t/t3455-history-squash.sh | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/builtin/history.c b/builtin/history.c
index 64c9914c2f..4dcfdb109d 100644
--- a/builtin/history.c
+++ b/builtin/history.c
@@ -1087,6 +1087,10 @@ static int resolve_squash_range(struct repository *repo,
 		if (commit->object.flags & BOUNDARY) {
 			commit_list_insert(commit, &boundaries);
 			continue;
+		}
+		if (!commit->parents) {
+			ret = error(_("cannot squash down to root commit"));
+			goto out;
 		}
 		if (!oldest)
 			oldest = commit;
diff --git a/t/t3455-history-squash.sh b/t/t3455-history-squash.sh
index 9c362f3094..b181f93892 100755
--- a/t/t3455-history-squash.sh
+++ b/t/t3455-history-squash.sh
@@ -64,6 +64,18 @@ test_expect_success 'errors on a range holding a single commit' '
 	test_must_fail git history squash "HEAD^!" 2>err &&
 	test_grep "single commit; nothing to squash" err &&
 	test_cmp_rev "$head_before" HEAD
+'
+
+test_expect_success 'rejects root commit' '
+	# create a disconnected root commit
+	oid=$(git commit-tree -m root three^{tree}) &&
+	# because we pass --ancestry-path when calling setup_revs() it the
+	# revision walk will only include commits decended from $oid so
+	# we need to give it another --ancestry-path commit to actually walk
+	# any commits.
+	test_must_fail git history squash --ancestry-path=start $oid..three 2>err &&
+	echo "error: cannot squash down to root commit" >expect &&
+	test_cmp expect err
 '
 
 test_expect_success 'accepts multiple revision arguments with an exclusion' '
-- 
2.54.0.200.gfd8d68259e3