git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] cat-file.c: add batch handling for submodules

From
Victoria Dye via GitGitGadget <gitgitgadget@gmail.com>
Date
Jun 2, 2025, 18:55 UTC
Message-ID
<980ab7f7ef56944df78530dcc9c79b54d1450806.1748890555.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1929.git.1748890555.gitgitgadget@gmail.com>
From: Victoria Dye <vdye@github.com>

When an object specification is passed to 'cat-file --batch[-check]' referring to a submodule (e.g. 'HEAD:path/to/my/submodule'), the current behavior of the command is to print the "missing" error message. However, it is often valuable for callers to distinguish between paths that are actually missing and "the submodule tree entry exists, but the object does not exist in the repository".

To disambiguate without needing to invoke a separate Git process (e.g. 'ls-tree'), print the message "<oid> submodule" for such objects instead of "<object> missing". In addition to the change from "missing" to "submodule", the new message differs from the old in that it always prints the resolved tree entry's OID, rather than the input object specification.

Note that this implementation maintains a distinction between submodules where the commit OID is not present in the repo, and submodules where the commit OID *is* present; the former will now print "<object> submodule", but the latter will still print the full object content.

Signed-off-by: Victoria Dye <vdye@github.com>
---
 Documentation/git-cat-file.adoc |  8 ++++++++
 builtin/cat-file.c              |  5 ++++-
 t/t1006-cat-file.sh             | 25 +++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc
index 5c002c0499e4..180d1ad363fd 100644
--- a/Documentation/git-cat-file.adoc
+++ b/Documentation/git-cat-file.adoc
@@ -373,6 +373,14 @@ If a name is specified that might refer to more than one object (an ambiguous sh
 <object> SP ambiguous LF
 ------------
 
+If a name is specified that refers to a submodule entry in a tree and the
+target object does not exist in the repository, then `cat-file` will ignore
+any custom format and print (with the object ID of the submodule):
+
+------------
+<oid> SP submodule LF
+------------
+
 If `--follow-symlinks` is used, and a symlink in the repository points
 outside the repository, then `cat-file` will ignore any custom format
 and print:
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index b11576756bcc..4b23fcecbd8e 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -496,7 +496,10 @@ static void batch_object_write(const char *obj_name,
 						       &data->oid, &data->info,
 						       OBJECT_INFO_LOOKUP_REPLACE);
 		if (ret < 0) {
-			report_object_status(opt, obj_name, &data->oid, "missing");
+			if (data->mode == S_IFGITLINK)
+				report_object_status(opt, oid_to_hex(&data->oid), &data->oid, "submodule");
+			else
+				report_object_status(opt, obj_name, &data->oid, "missing");
 			return;
 		}
 
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 97052b3f31f1..f123ef1e360a 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -1220,6 +1220,31 @@ test_expect_success 'cat-file --batch-check respects replace objects' '
 	test_cmp expect actual
 '
 
+test_expect_success 'batch-check with a submodule' '
+	# FIXME: this call to mktree is incompatible with compatObjectFormat
+	# because the submodule OID cannot be mapped to the compat hash algo.
+	test_unconfig extensions.compatobjectformat &&
+	printf "160000 commit $(test_oid deadbeef)\tsub\n" >tree-with-sub &&
+	tree=$(git mktree <tree-with-sub) &&
+	test_config extensions.compatobjectformat $test_compat_hash_algo &&
+
+	git cat-file --batch-check >actual <<-EOF &&
+	$tree:sub
+	EOF
+	printf "$(test_oid deadbeef) submodule\n" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'batch-check with a submodule, object exists' '
+	printf "160000 commit $commit_oid\tsub\n" >tree-with-sub &&
+	tree=$(git mktree <tree-with-sub) &&
+	git cat-file --batch-check >actual <<-EOF &&
+	$tree:sub
+	EOF
+	printf "$commit_oid commit $commit_size\n" >expect &&
+	test_cmp expect actual
+'
+
 # Pull the entry for object with oid "$1" out of the output of
 # "cat-file --batch", including its object content (which requires
 # parsing and reading a set amount of bytes, hence perl).
-- 
gitgitgadget
Previous: Jeff KingNext: Jeff King
Message 5 of 10 in “cat-file: add %(objectmode) and submodule message to batch commands”
  1. 0/3 cat-file: add %(objectmode) and submodule message to batch commandsVictoria Dye via GitGitGadget, Jun 2, 2025
  2. 1/3 t1006: update 'run_tests' to test generic object specifiersVictoria Dye via GitGitGadget, Jun 2, 2025
  3. 2/3 cat-file: add %(objectmode) atomVictoria Dye via GitGitGadget, Jun 2, 2025
  4. Jeff KingJun 4, 2025
  5. 3/3 cat-file.c: add batch handling for submodulesVictoria Dye via GitGitGadget, Jun 2, 2025
  6. Jeff KingJun 4, 2025
  7. Victoria DyeJun 5, 2025
  8. Jeff KingJun 5, 2025
  9. Junio C HamanoJun 4, 2025
  10. Jeff KingJun 4, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.