subtree: validate --prefix against commit in split

git subtree split currently validates --prefix against the working tree. This breaks when splitting an older commit or when the working tree does not contain the subtree, even though the commit does. For example: git subtree split --prefix=pkg <commit> fails if pkg was removed later, even though it exists in <commit>. Fix this by validating the prefix against the specified commit using git cat-file instead of the working tree. Add a test to ensure this behavior does not regress. Signed-off-by: Pushkar Singh <pushkarkumarsingh1970@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Pushkar Singh committed Feb 3, 2026 at 16:48 UTC a606fcdceb807b93013542e5e4d5f4c233aa6c83
2 files changed +31
contrib/subtree/git-subtree.sh
+9
@@ -257,6 +257,9 @@ main () {
257 test -e "$arg_prefix" &&
258 die "fatal: prefix '$arg_prefix' already exists."
259 ;;
260 + split)
261 + # checked later against the commit, not the working tree
262 + ;;
263 *)
264 test -e "$arg_prefix" ||
265 die "fatal: '$arg_prefix' does not exist; use 'git subtree add'"
@@ -966,6 +969,12 @@ cmd_split () {
969 else
970 die "fatal: you must provide exactly one revision, and optionally a repository. Got: '$*'"
971 fi
972 +
973 + # Now validate prefix against the commit, not the working tree
974 + if ! git cat-file -e "$rev:$dir" 2>/dev/null
975 + then
976 + die "fatal: '$dir' does not exist; use 'git subtree add'"
977 + fi
978 repository=""
979 if test "$#" = 2
980 then
contrib/subtree/t/t7900-subtree.sh
+22
@@ -368,6 +368,28 @@ test_expect_success 'split requires path given by option --prefix must exist' '
368 )
369 '
370
371 +test_expect_success 'split works when prefix exists in commit but not in working tree' '
372 + subtree_test_create_repo "$test_count" &&
373 + (
374 + cd "$test_count" &&
375 +
376 + # create subtree
377 + mkdir pkg &&
378 + echo ok >pkg/file &&
379 + git add pkg &&
380 + git commit -m "add pkg" &&
381 + good=$(git rev-parse HEAD) &&
382 +
383 + # remove it from working tree in later commit
384 + git rm -r pkg &&
385 + git commit -m "remove pkg" &&
386 +
387 + # must still be able to split using the old commit
388 + git subtree split --prefix=pkg "$good" >out &&
389 + test -s out
390 + )
391 +'
392 +
393 test_expect_success 'split rejects flags for add' '
394 subtree_test_create_repo "$test_count" &&
395 subtree_test_create_repo "$test_count/sub proj" &&