Git development
 help / color / mirror / Atom feed
* [PATCH] ls-remote: add --show-object-format
@ 2026-11-05 10:45 Adrian Ratiu
  2026-11-05 14:13 ` Patrick Steinhardt
  0 siblings, 1 reply; 3+ messages in thread
From: Adrian Ratiu @ 2026-11-05 10:45 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, brian m . carlson, Axel Rasmussen, Emily Shaffer,
	Josh Steadmon, Adrian Ratiu

While working on JJ sha256 remote support (it uses Git for networking),
I noticed there is no way to get the object format of a repo without
cloning it. [1]

Git clone learns the remote format during the protocol handshake, but
it is not shown anywhere else. For example, when creating an empty repo
and running "git fetch":

1. If the remote has references, fetch can fail with a mismatch error
and "git ls-remote" shows the format indirectly through the length
of the object IDs. Not ideal, but the it can be figured out eventually.

2. If the remote is empty, "git ls-remote" prints nothing and fetch
succeeds, so the new local repo can silently get the wrong format,
which only shows up later, on the first push.

To fill this gap, add a ls-remote --show-object-format option which
prints the object format learned from the remote on a line of its own,
before the references.

[1]: https://github.com/jj-vcs/jj/issues/3813

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
---
 Documentation/git-ls-remote.adoc | 10 ++++++-
 builtin/ls-remote.c              |  8 +++++-
 t/t5512-ls-remote.sh             | 46 ++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-ls-remote.adoc b/Documentation/git-ls-remote.adoc
index d71c4ab3e2..1abf7b60b7 100644
--- a/Documentation/git-ls-remote.adoc
+++ b/Documentation/git-ls-remote.adoc
@@ -11,7 +11,8 @@ SYNOPSIS
 [verse]
 'git ls-remote' [--branches] [--tags] [--refs] [--upload-pack=<exec>]
 	      [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
-	      [--symref] [<repository> [<patterns>...]]
+	      [--symref] [--show-object-format]
+	      [<repository> [<patterns>...]]
 
 DESCRIPTION
 -----------
@@ -64,6 +65,13 @@ OPTIONS
 	upload-pack only shows the symref HEAD, so it will be the only
 	one shown by ls-remote.
 
+--show-object-format::
+	Show the object format (hash algorithm, e.g. `sha1` or `sha256`) used
+	by the remote repository before printing the references, on a line of
+	its own. This also works for a remote repo without any refs, which is
+	useful to find out which object format to use for a local repository,
+	before pushing or fetching the new remote.
+
 --sort=<key>::
 	Sort based on the key given. Prefix `-` to sort in descending order
 	of the value. Supports "version:refname" or "v:refname" (tag names
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index fe77829557..6d961f9961 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -12,7 +12,8 @@
 static const char * const ls_remote_usage[] = {
 	N_("git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n"
 	   "              [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
-	   "              [--symref] [<repository> [<patterns>...]]"),
+	   "              [--symref] [--show-object-format]\n"
+	   "              [<repository> [<patterns>...]]"),
 	NULL
 };
 
@@ -49,6 +50,7 @@ int cmd_ls_remote(int argc,
 	int quiet = 0;
 	int status = 0;
 	int show_symref_target = 0;
+	int show_object_format = 0;
 	const char *uploadpack = NULL;
 	struct strvec pattern = STRVEC_INIT;
 	struct transport_ls_refs_options transport_options =
@@ -89,6 +91,8 @@ int cmd_ls_remote(int argc,
 			      2, PARSE_OPT_NOCOMPLETE),
 		OPT_BOOL(0, "symref", &show_symref_target,
 			 N_("show underlying ref in addition to the object pointed by it")),
+		OPT_BOOL(0, "show-object-format", &show_object_format,
+			 N_("show the object format used by the remote repository")),
 		OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
 		OPT_END()
 	};
@@ -150,6 +154,8 @@ int cmd_ls_remote(int argc,
 
 	if (!dest && !quiet)
 		fprintf(stderr, "From %s\n", remote->url.v[0]);
+	if (show_object_format)
+		printf("%s\n", transport_get_hash_algo(transport)->name);
 	for ( ; ref; ref = ref->next) {
 		struct ref_array_item *item;
 		if (!check_ref_type(ref, flags))
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 2e1d4f7586..7e82154fe4 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -332,6 +332,52 @@ test_expect_success 'indicate no refs in v0 standards-compliant empty remote' '
 	test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input .
 '
 
+# Run "ls-remote --show-object-format" with the given arguments over
+# protocol v0 and v2, and compare its output with "expect".
+test_show_object_format () {
+	for version in 0 2
+	do
+		git -c protocol.version=$version \
+			ls-remote --show-object-format "$@" >actual &&
+		test_cmp expect actual || return 1
+	done
+}
+
+test_expect_success 'ls-remote --show-object-format with empty sha1 remote' '
+	git init --bare --object-format=sha1 empty-sha1.git &&
+	echo sha1 >expect &&
+	test_show_object_format empty-sha1.git
+'
+
+test_expect_success 'ls-remote --show-object-format with empty sha256 remote' '
+	git init --bare --object-format=sha256 empty-sha256.git &&
+	echo sha256 >expect &&
+	test_show_object_format empty-sha256.git
+'
+
+test_expect_success 'ls-remote --show-object-format with sha1 remote' '
+	git init --object-format=sha1 repo-sha1 &&
+	test_commit -C repo-sha1 one &&
+	oid=$(git -C repo-sha1 rev-parse HEAD) &&
+	printf "sha1\n%s\tHEAD\n" "$oid" >expect &&
+	test_show_object_format repo-sha1 HEAD
+'
+
+test_expect_success 'ls-remote --show-object-format with sha256 remote' '
+	git init --object-format=sha256 repo-sha256 &&
+	test_commit -C repo-sha256 one &&
+	oid=$(git -C repo-sha256 rev-parse HEAD) &&
+	printf "sha256\n%s\tHEAD\n" "$oid" >expect &&
+	test_show_object_format repo-sha256 HEAD
+'
+
+test_expect_success 'ls-remote --show-object-format outside repository' '
+	nongit git init --bare --object-format=sha256 empty-nongit.git &&
+	echo sha256 >expect &&
+	nongit git ls-remote --show-object-format empty-nongit.git >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'ls-remote works outside repository' '
 	# It is important for this repo to be inside the nongit
 	# area, as we want a repo name that does not include
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-05 16:36 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-05 10:45 [PATCH] ls-remote: add --show-object-format Adrian Ratiu
2026-11-05 14:13 ` Patrick Steinhardt
2026-11-05 16:35   ` Adrian Ratiu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox