git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GSoC][PATCH 0/2] Add refs exists subcommand
@ 2025-08-21  8:52 Meet Soni
  2025-08-21  8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
                   ` (4 more replies)
  0 siblings, 5 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-21  8:52 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, Meet Soni

This series introduces `git refs exists` as a modern replacement for
`git show-ref --exists`, continuing the effort to consolidate commands
under the `git refs` namespace.

The two patches are as follows:

1. The first implements the `exists` subcommand. The small amount of
   logic is duplicated from `show-ref` to avoid unnecessary abstraction.

2. The second adds tests by refactoring the `show-ref --exists` tests
   into a shareable helper, ensuring both commands are tested for
   identical behavior.

Meet Soni (2):
  builtin/refs: add 'exists' subcommand
  t: add test for git refs exists subcommand

 Documentation/git-refs.adoc |  7 ++++
 builtin/refs.c              | 48 +++++++++++++++++++++++++++
 t/meson.build               |  3 +-
 t/show-ref-exists-tests.sh  | 66 +++++++++++++++++++++++++++++++++++++
 t/t1403-show-ref.sh         | 66 +------------------------------------
 t/t1462-refs-exists.sh      | 22 +++++++++++++
 6 files changed, 146 insertions(+), 66 deletions(-)
 create mode 100644 t/show-ref-exists-tests.sh
 create mode 100755 t/t1462-refs-exists.sh


base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
prerequisite-patch-id: d0cb9932dcf233b3a26e413514375191ede93c73
prerequisite-patch-id: 9cb324ad34a786af110e9d3d47e4ca8aec240971
prerequisite-patch-id: 0d74ac673c285c334adcc19b9ca2d4919563e804
prerequisite-patch-id: 04c6d989f4130a063bc80f7dc9ce9a16d3459665
prerequisite-patch-id: 95dafb2692da02d79c59cc2742258a915da25e88
prerequisite-patch-id: f14c9a47038305eb3cfe8e9b649fa64065ada9cd
prerequisite-patch-id: 6923112c5bbec8f7f89d4a978cd2dd8e3eb55630
prerequisite-patch-id: 68baea3d311384cf9b8685ad874bb1b103a81f7d
prerequisite-patch-id: 2378c874394d7805730a46879d03da0bef244adb
prerequisite-patch-id: d329083ff7ea2fb57c984c4c4718bbb793fea13d
prerequisite-patch-id: 9b34591269ae3de243da1ae750878b7f6b29da07
prerequisite-patch-id: e3fa9191e8bc9e281adaf7c056644073e0b99dc9
prerequisite-patch-id: d3ecaf8354dc1d58dc70a9d9ea51508ceff2b2e1
prerequisite-patch-id: 90cd997029c15397eceb219d0d22989d9e874a92
prerequisite-patch-id: 37e3430d0a76fcdd8f6853c311f76aa18ba4f430
prerequisite-patch-id: 358ee0b96796c09458b03c35739268866a2c36df
prerequisite-patch-id: 50119e8583f0bcf8c275758d1955682643974687
prerequisite-patch-id: d85f18fb917f1affeefd4f807c7a8114fa6adb16
prerequisite-patch-id: 84e6b5171ddd6f5736196cbe79549f4186b85981
prerequisite-patch-id: d4b4473d029ea8df05668f9bfd767a9272255e3f
prerequisite-patch-id: 8cb9a456888b52813ef095b7f997dab5f390df0a
prerequisite-patch-id: 4e16bf58775a0dbbf58302f21d11864b96f321eb
prerequisite-patch-id: eabfc6cb85b47f04d78c2634dbaa6fddf87a60f9
prerequisite-patch-id: 15aad03c722b62d6fa22bdc3a44f862ebc2b1c88
prerequisite-patch-id: 9361523cda8f829d5fb7cef7d234f3fda99ebb9b
prerequisite-patch-id: 66abfbef34f4f7bc408324c5f327b767ef36a679
prerequisite-patch-id: 449ca227be630deeced22f191344becc63cdf9d1
prerequisite-patch-id: 5226b03a040940b4fe1bf0af254a77d67f5a177e
prerequisite-patch-id: e7c24bcc4a5ed5367e90bb23db0e28d0ccbdad2a
prerequisite-patch-id: abfc3c9c3ea59b7495e229e9ad433f60dc0ff8f7
prerequisite-patch-id: 7fe80bfc019f63df308391e1127a25e59103abc2
prerequisite-patch-id: a84ad0fb4b321a8d6c58d942a716b8e3748156ba
prerequisite-patch-id: 900b6cbe5278bc6beeadc102509f1385ce7d637e
prerequisite-patch-id: c7ad0ca2ff0e22d174da1047c6eb30b1dcd8da84
prerequisite-patch-id: 118017529d699ca93d9ee86196eac8557f5c36a1
prerequisite-patch-id: 49b0a7b7e607adb614e7b46d2778ac46d3b3c7ce
prerequisite-patch-id: 823f58165b365d7368faa82d905fe0d0c2136357
prerequisite-patch-id: 665b97ae5be824000628b34bdbb2b73b68b5c292
prerequisite-patch-id: e3c140859b3637d5a13c020ef041ad25a4a6bc42
prerequisite-patch-id: 41cb62f978e5dbf3a658ffffe99b8c1b479938a1
prerequisite-patch-id: 1929619486cdee7517c3f2b0af67e96c69c89764
prerequisite-patch-id: 5035d6f130dfc22b4fe9ea79b7a436fd54070a81
prerequisite-patch-id: 53dd4f1d4455d8cdf2e2a2fcb082be00ad8c0914
prerequisite-patch-id: 2efcbefc0f0395e8178e656c3c79cea2acf54377
prerequisite-patch-id: 447c1cb43a64eb6c95d98e115fcbf424492a3ab5
prerequisite-patch-id: f929f5f303123f8b937cb94c200ba93b139b9dfb
prerequisite-patch-id: 373824b744f085cd7bfd97f1568c6f2d56ea8ca2
prerequisite-patch-id: e4dfe5bca99ff093f0c8aff1a085010c0f0d3c6f
prerequisite-patch-id: ca8fe616ea1ac4d575747f9224222bd65f514705
prerequisite-patch-id: d34e569010a2beb0d5ddfe7e3dedf3abb77c5604
prerequisite-patch-id: 250bae2541030fcdfc5b35ede44c23e1138c7a3c
prerequisite-patch-id: 476284f1a96b09b8853052c9ba8f32acb2834c17
prerequisite-patch-id: 9cd780236535e9e84eae38f2a19c5e010f6c1288
prerequisite-patch-id: 7e3ba2fb3d0dd0760a3e3a5b336927b04999b28a
prerequisite-patch-id: 0a500a41e9feeca41e81bb0e1bfcf3ddfbe4cb82
prerequisite-patch-id: a11fa19efa109c1394e0c6ab781720c61ce13c41
prerequisite-patch-id: b365ab543df9d138b41c1a8d40a754b84b965e99
prerequisite-patch-id: 6f248fa00c78e2171a52f4c038d4bd7f339840b2
prerequisite-patch-id: fb1e7d4305f77c598936f4b638fa7803965c9e78
prerequisite-patch-id: 5b1b57b2c3fb387b3fbd7a9c6f0b57c80199a94d
prerequisite-patch-id: 9d70dcb2e265c49f9b84afafa56c857567943a04
prerequisite-patch-id: cf13b44e4629fbf488603defcbc8acdc0217b4be
prerequisite-patch-id: c90829faf86b799652917ef99206e7b1cead2c54
prerequisite-patch-id: b076beae979d5ac7fedcc13b5d26e77d5cbe6663
prerequisite-patch-id: 5f39ac2a8c07870f69770baa0109793ff7022076
prerequisite-patch-id: cafedb553cd007249c5bfcac36242438656ca170
prerequisite-patch-id: 197d745dfcefbd8751e0c90aac632331826752a1
prerequisite-patch-id: 0d1d1a35ed44cf830442f3e74c65cdcdf9b91566
prerequisite-patch-id: 4cc86520dd4d680ee3ca856d176f324e683eca41
prerequisite-patch-id: 95a6721029877cf75106b96a6bcc707aa17e1b9c
prerequisite-patch-id: 5b7734071f21d853533a6ee09383690fafb5fead
prerequisite-patch-id: 7e1d3e7927abac3b453fd0e79b634c7365ed955a
prerequisite-patch-id: 7daea73cac876045f587001cf94b7f83ee9e12c4
prerequisite-patch-id: a765074cb9084aa5da8e72b2690c323c3ec83231
prerequisite-patch-id: 4e277720b943d0a26cc85adda11eb568e442f77b
prerequisite-patch-id: 28f977860324220a487487be0704519f90a02306
prerequisite-patch-id: 08e65a7035bac5c4232ea4e39c54eecc49408f19
prerequisite-patch-id: 63c3e610f0e56eabc039483636e292d05bbc63b9
prerequisite-patch-id: bedd7161331cb4fbf30debff40d33a8a0c14023f
prerequisite-patch-id: bf6dd38daaf71b4599833e4c8cbf64698e9c1a36
prerequisite-patch-id: c611631180a541b1787c12bcbe64bb9ae3454244
prerequisite-patch-id: f3368c4816df6c93c1ec1b35c1c405657f1a7387
prerequisite-patch-id: 29c35a90c70a4f37baf96b4f592e197c5621666a
prerequisite-patch-id: 6a612f309924935068f6a57f8d181d842a274ea5
prerequisite-patch-id: 76634063b4f24689276d6099bade4330c3fa8bde
prerequisite-patch-id: e217cab3cdd411bad09c252de5fb4206be77d637
prerequisite-patch-id: bb3fbaa2b7bd78e3e60f7a434146005c04161509
prerequisite-patch-id: 24edfd0bf766d61c182de3aa86377ae90db4f7ef
prerequisite-patch-id: bcc3a15b67760ab9433363223c506cd09f03747e
prerequisite-patch-id: e7bd2d09677a0bb1019e3c3790417498ba2dc7f2
prerequisite-patch-id: c79540346ad559338d46454486dcc1be25e9c5a1
prerequisite-patch-id: 8803357fd1432a264d60c9e1a688dc85d7935b3e
prerequisite-patch-id: c099a26d62f63b535199c6f52271bb63e88df69c
prerequisite-patch-id: d1825e57939cbd15928498352e1a7f00c673c12d
prerequisite-patch-id: 3ebef3d7a7a7b224eb0a68ec8edfa0358a2c5a7b
prerequisite-patch-id: 69f3f6729c7c473374a9f21ec2875b8e42ea5cd9
prerequisite-patch-id: 2c5dc68c7b4811b6710cf1516cbd3608cc761bbc
prerequisite-patch-id: 0803b4f82635672ea9b6b9a546d9a9577884c5ad
prerequisite-patch-id: 553adfe23223a427db3f93e23dfb603c55cc5aae
-- 
2.34.1


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

* [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand
  2025-08-21  8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
@ 2025-08-21  8:52 ` Meet Soni
  2025-08-21 10:21   ` Patrick Steinhardt
  2025-08-21  8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 23+ messages in thread
From: Meet Soni @ 2025-08-21  8:52 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, Meet Soni

As part of the ongoing effort to consolidate reference handling,
introduce a new `exists` subcommand. This command provides the same
functionality and exit-code behavior as `git show-ref --exists`, serving
as its modern replacement.

The logic for `show-ref --exists` is minimal. Rather than creating a
shared helper function which would be overkill for ~20 lines of code,
its implementation is intentionally duplicated here. This contrasts with
`git refs list`, where sharing the larger implementation of
`for-each-ref` was necessary.

Documentation for the new subcommand is also added to the `git-refs(1)`
man page.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 Documentation/git-refs.adoc |  7 ++++++
 builtin/refs.c              | 48 +++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index d462953fb5..bfa9b3ea2d 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
 		   [--contains[=<object>]] [--no-contains[=<object>]]
 		   [(--exclude=<pattern>)...] [--start-after=<marker>]
 		   [ --stdin | (<pattern>...)]
+git refs exists <ref>
 
 DESCRIPTION
 -----------
@@ -38,6 +39,12 @@ list::
 	formatting, and sorting. This subcommand is an alias for
 	linkgit:git-for-each-ref[1] and offers identical functionality.
 
+exists::
+	Check whether the given reference exists. Returns an exit code of 0 if
+	it does, 2 if it is missing, and 1 in case looking up the reference
+	failed with an error other than the reference being missing. This does
+	not verify whether the reference resolves to an actual object.
+
 OPTIONS
 -------
 
diff --git a/builtin/refs.c b/builtin/refs.c
index 76224feba4..617d8ab138 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -7,6 +7,7 @@
 #include "strbuf.h"
 #include "worktree.h"
 #include "for-each-ref.h"
+#include "refs/refs-internal.h"
 
 #define REFS_MIGRATE_USAGE \
 	N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -14,6 +15,9 @@
 #define REFS_VERIFY_USAGE \
 	N_("git refs verify [--strict] [--verbose]")
 
+#define REFS_EXISTS_USAGE \
+	N_("git refs exists <ref>")
+
 static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
 			    struct repository *repo UNUSED)
 {
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
 	return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
 }
 
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+			   struct repository *repo UNUSED)
+{
+	struct strbuf unused_referent = STRBUF_INIT;
+	struct object_id unused_oid;
+	unsigned int unused_type;
+	int failure_errno = 0;
+	const char *ref;
+
+	const char * const exists_usage[] = {
+		REFS_EXISTS_USAGE,
+		NULL,
+	};
+	struct option options[] = {
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+	if (!argc)
+		die("'git refs exists' requires a reference");
+
+	ref = *argv++;
+	if (*argv)
+		die("'git refs exists' requires exactly one reference");
+
+	if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+			      &unused_oid, &unused_referent, &unused_type,
+			      &failure_errno)) {
+		if (failure_errno == ENOENT || failure_errno == EISDIR) {
+			error(_("reference does not exist"));
+			return 2;
+		} else {
+			errno = failure_errno;
+			error_errno(_("failed to look up reference"));
+			return 1;
+		}
+	}
+
+	strbuf_release(&unused_referent);
+	return 0;
+}
+
 int cmd_refs(int argc,
 	     const char **argv,
 	     const char *prefix,
@@ -122,6 +168,7 @@ int cmd_refs(int argc,
 		REFS_MIGRATE_USAGE,
 		REFS_VERIFY_USAGE,
 		"git refs list " COMMON_USAGE_FOR_EACH_REF,
+		REFS_EXISTS_USAGE,
 		NULL,
 	};
 	parse_opt_subcommand_fn *fn = NULL;
@@ -129,6 +176,7 @@ int cmd_refs(int argc,
 		OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
 		OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
 		OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+		OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
 		OPT_END(),
 	};
 
-- 
2.34.1


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

* [GSoC][PATCH 2/2] t: add test for git refs exists subcommand
  2025-08-21  8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
  2025-08-21  8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-21  8:52 ` Meet Soni
  2025-08-21 10:21   ` Patrick Steinhardt
  2025-08-21 10:21 ` [GSoC][PATCH 0/2] Add " Patrick Steinhardt
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 23+ messages in thread
From: Meet Soni @ 2025-08-21  8:52 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, Meet Soni

The new `git refs exists` subcommand must have identical behavior to its
predecessor, `git show-ref --exists`. To avoid duplicating the entire
test suite, refactor the existing tests into a shareable helper script.

Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
a new `show-ref-exists-tests.sh` helper. The command under test is
parameterized using the `$git_show_ref_exists` variable.

Source new helper to both `t1403-show-ref.sh` and the new test file,
`t1462-refs-exists.sh`, ensuring both commands are verified against the
same comprehensive test suite.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/meson.build              |  3 +-
 t/show-ref-exists-tests.sh | 66 ++++++++++++++++++++++++++++++++++++++
 t/t1403-show-ref.sh        | 66 +-------------------------------------
 t/t1462-refs-exists.sh     | 22 +++++++++++++
 4 files changed, 91 insertions(+), 66 deletions(-)
 create mode 100644 t/show-ref-exists-tests.sh
 create mode 100755 t/t1462-refs-exists.sh

diff --git a/t/meson.build b/t/meson.build
index baeeba2ce6..eed812a9b9 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -211,6 +211,7 @@ integration_tests = [
   't1451-fsck-buffer.sh',
   't1460-refs-migrate.sh',
   't1461-refs-list.sh',
+  't1462-refs-exists.sh',
   't1500-rev-parse.sh',
   't1501-work-tree.sh',
   't1502-rev-parse-parseopt.sh',
@@ -1219,4 +1220,4 @@ if perl.found() and time.found()
       timeout: 0,
     )
   endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..23b941d386
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,66 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+
+test_expect_success '--exists with existing reference' '
+	${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+	test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+	test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+	grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+	${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+	test_when_finished "git update-ref -d refs/heads/bad...name" &&
+	new_oid=$(git rev-parse HEAD) &&
+	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+	test_when_finished "git symbolic-ref -d refs/symref" &&
+	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+	${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+	tree_oid=$(git rev-parse HEAD^{tree}) &&
+	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+	cat >expect <<-EOF &&
+	error: reference does not exist
+	EOF
+	test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+	test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+	test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+	test_when_finished "rm .git/FETCH_HEAD" &&
+	git rev-parse HEAD >.git/FETCH_HEAD &&
+	${git_show_ref_exists} FETCH_HEAD
+'
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..dbae82384b 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,5 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
 	grep "cannot be used together" err
 '
 
-test_expect_success '--exists with existing reference' '
-	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
-	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
-	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
-	grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
-	git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
-	test_when_finished "git update-ref -d refs/heads/bad...name" &&
-	new_oid=$(git rev-parse HEAD) &&
-	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
-	git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
-	test_when_finished "git symbolic-ref -d refs/symref" &&
-	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
-	git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
-	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
-	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
-	git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
-	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
-	tree_oid=$(git rev-parse HEAD^{tree}) &&
-	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
-	cat >expect <<-EOF &&
-	error: reference does not exist
-	EOF
-	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
-	test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
-	test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
-	test_when_finished "rm .git/FETCH_HEAD" &&
-	git rev-parse HEAD >.git/FETCH_HEAD &&
-	git show-ref --exists FETCH_HEAD
-'
-
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
 test_done
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..c00d76cc9e
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+
+test_expect_success setup '
+	test_commit --annotate A &&
+	git checkout -b side &&
+	test_commit --annotate B &&
+	git checkout main &&
+	test_commit C &&
+	git branch B A^0
+'
+
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
+
+test_done
-- 
2.34.1


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

* Re: [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand
  2025-08-21  8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-21 10:21   ` Patrick Steinhardt
  0 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:21 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, shejialuo

On Thu, Aug 21, 2025 at 02:22:45PM +0530, Meet Soni wrote:
> As part of the ongoing effort to consolidate reference handling,
> introduce a new `exists` subcommand. This command provides the same
> functionality and exit-code behavior as `git show-ref --exists`, serving
> as its modern replacement.
> 
> The logic for `show-ref --exists` is minimal. Rather than creating a
> shared helper function which would be overkill for ~20 lines of code,
> its implementation is intentionally duplicated here. This contrasts with
> `git refs list`, where sharing the larger implementation of
> `for-each-ref` was necessary.

I agree with this decision. It doesn't really feel worth it to share
code for such trivial functionality.

> diff --git a/builtin/refs.c b/builtin/refs.c
> index 76224feba4..617d8ab138 100644
> --- a/builtin/refs.c
> +++ b/builtin/refs.c
> @@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
>  	return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
>  }
>  
> +static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
> +			   struct repository *repo UNUSED)
> +{
> +	struct strbuf unused_referent = STRBUF_INIT;
> +	struct object_id unused_oid;
> +	unsigned int unused_type;
> +	int failure_errno = 0;
> +	const char *ref;
> +

Let's drop this empty newline.

> +	const char * const exists_usage[] = {
> +		REFS_EXISTS_USAGE,
> +		NULL,
> +	};
> +	struct option options[] = {
> +		OPT_END(),
> +	};
> +
> +	argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
> +	if (!argc)
> +		die("'git refs exists' requires a reference");
> +
> +	ref = *argv++;
> +	if (*argv)
> +		die("'git refs exists' requires exactly one reference");

We can combine these two error messages to just say `if (argc != 1)`.
Also, the strings should be marked for translation.

> +	if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
> +			      &unused_oid, &unused_referent, &unused_type,
> +			      &failure_errno)) {
> +		if (failure_errno == ENOENT || failure_errno == EISDIR) {
> +			error(_("reference does not exist"));
> +			return 2;
> +		} else {
> +			errno = failure_errno;
> +			error_errno(_("failed to look up reference"));
> +			return 1;

I'd personally prefer to se a common exit path and use `goto` so that
one doesn't have to worry about whether or not the `struct strbuf` needs
to be free'd in error cases. But I'll leave it up to you to decide
whether you want to do this change.

Patrick

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

* Re: [GSoC][PATCH 2/2] t: add test for git refs exists subcommand
  2025-08-21  8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
@ 2025-08-21 10:21   ` Patrick Steinhardt
  2025-08-22  4:59     ` Meet Soni
  0 siblings, 1 reply; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:21 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, shejialuo

On Thu, Aug 21, 2025 at 02:22:46PM +0530, Meet Soni wrote:
> The new `git refs exists` subcommand must have identical behavior to its
> predecessor, `git show-ref --exists`. To avoid duplicating the entire
> test suite, refactor the existing tests into a shareable helper script.
> 
> Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
> a new `show-ref-exists-tests.sh` helper. The command under test is
> parameterized using the `$git_show_ref_exists` variable.
> 
> Source new helper to both `t1403-show-ref.sh` and the new test file,

s/new/this/, otherwise this reads grammatically wrong to me.

>  test_done
> diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
> new file mode 100755
> index 0000000000..c00d76cc9e
> --- /dev/null
> +++ b/t/t1462-refs-exists.sh
> @@ -0,0 +1,22 @@
> +#!/bin/sh
> +
> +test_description='refs exists'
> +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> +
> +. ./test-lib.sh
> +
> +git_show_ref_exists='git refs exists'
> +
> +test_expect_success setup '
> +	test_commit --annotate A &&
> +	git checkout -b side &&
> +	test_commit --annotate B &&
> +	git checkout main &&
> +	test_commit C &&
> +	git branch B A^0
> +'

It's a bit weird that this setup needs to be replicated. I guess it
comes from the fact that t1403 also has a bunch of other tests for
git-show-ref(1) that are irrelevant to existence checks.

How about we instead split out the existence-checks in t1403 into a
separate test suite first and then pull out the whole logic from it in a
subsequent commit so that we can also share the setup?

Patrick

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

* Re: [GSoC][PATCH 0/2] Add refs exists subcommand
  2025-08-21  8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
  2025-08-21  8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
  2025-08-21  8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
@ 2025-08-21 10:21 ` Patrick Steinhardt
  2025-08-21 16:01 ` Junio C Hamano
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
  4 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-21 10:21 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, shejialuo

On Thu, Aug 21, 2025 at 02:22:44PM +0530, Meet Soni wrote:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
> 
> The two patches are as follows:
> 
> 1. The first implements the `exists` subcommand. The small amount of
>    logic is duplicated from `show-ref` to avoid unnecessary abstraction.
> 
> 2. The second adds tests by refactoring the `show-ref --exists` tests
>    into a shareable helper, ensuring both commands are tested for
>    identical behavior.
> 
> Meet Soni (2):
>   builtin/refs: add 'exists' subcommand
>   t: add test for git refs exists subcommand
> 
>  Documentation/git-refs.adoc |  7 ++++
>  builtin/refs.c              | 48 +++++++++++++++++++++++++++
>  t/meson.build               |  3 +-
>  t/show-ref-exists-tests.sh  | 66 +++++++++++++++++++++++++++++++++++++
>  t/t1403-show-ref.sh         | 66 +------------------------------------
>  t/t1462-refs-exists.sh      | 22 +++++++++++++
>  6 files changed, 146 insertions(+), 66 deletions(-)
>  create mode 100644 t/show-ref-exists-tests.sh
>  create mode 100755 t/t1462-refs-exists.sh
> 
> 
> base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
> prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
> prerequisite-patch-id: d0cb9932dcf233b3a26e413514375191ede93c73
> prerequisite-patch-id: 9cb324ad34a786af110e9d3d47e4ca8aec240971
> prerequisite-patch-id: 0d74ac673c285c334adcc19b9ca2d4919563e804
> prerequisite-patch-id: 04c6d989f4130a063bc80f7dc9ce9a16d3459665
> prerequisite-patch-id: 95dafb2692da02d79c59cc2742258a915da25e88
> prerequisite-patch-id: f14c9a47038305eb3cfe8e9b649fa64065ada9cd
...

Feels like something went wrong here :)

What the cover letter doesn't mention explicitly is what the base of
this topic is. I assume it's probably v2.51.0 with ms/refs-list merged
into it?

Patrick

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

* Re: [GSoC][PATCH 0/2] Add refs exists subcommand
  2025-08-21  8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
                   ` (2 preceding siblings ...)
  2025-08-21 10:21 ` [GSoC][PATCH 0/2] Add " Patrick Steinhardt
@ 2025-08-21 16:01 ` Junio C Hamano
  2025-08-22  4:27   ` Meet Soni
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
  4 siblings, 1 reply; 23+ messages in thread
From: Junio C Hamano @ 2025-08-21 16:01 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, ps, shejialuo

Meet Soni <meetsoni3017@gmail.com> writes:

> base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
> prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
> ... (~100 lines of crap omitted)
> prerequisite-patch-id: 553adfe23223a427db3f93e23dfb603c55cc5aae

Please don't force others to go hunt to find so many patches before
being able to even recreate what you based your changes on.

Learn the way how it is usually done by looking at:

https://lore.kernel.org/git/20250106-b4-pks-object-file-racy-collision-check-v2-0-8b3984ecbb18@pks.im/

Basically you would want to say

    This is built on top of <commit> with <topic*> merged into it.

where <commit> is a commit on 'master' (or 'maint' or an even older
maintenance track, if the topic is about fixing a bug in a released
version of Git), and <topic*> are topic branches in flight that can
be merged to the same integration target ('master', or an older
maintenance tracks you chose <commit> from).  And keep the number of
<topic*> to an absolute minimum in order for your changes to work.

Thanks.

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

* Re: [GSoC][PATCH 0/2] Add refs exists subcommand
  2025-08-21 16:01 ` Junio C Hamano
@ 2025-08-22  4:27   ` Meet Soni
  0 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-22  4:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, ps, shejialuo

On Thu, 21 Aug 2025 at 21:31, Junio C Hamano <gitster@pobox.com> wrote:
>
> Meet Soni <meetsoni3017@gmail.com> writes:
>
> > base-commit: c44beea485f0f2feaf460e2ac87fdd5608d63cf0
> > prerequisite-patch-id: 235cc677f372e9571dade4313f8cfed4eab65f7f
> > ... (~100 lines of crap omitted)
> > prerequisite-patch-id: 553adfe23223a427db3f93e23dfb603c55cc5aae
>
> Please don't force others to go hunt to find so many patches before
> being able to even recreate what you based your changes on.
>
I was a bit confused between cherry-picking and basing my series on next, and I
ended up doing the latter. I’ll fix it.

> Learn the way how it is usually done by looking at:
>
> https://lore.kernel.org/git/20250106-b4-pks-object-file-racy-collision-check-v2-0-8b3984ecbb18@pks.im/
>
> Basically you would want to say
>
>     This is built on top of <commit> with <topic*> merged into it.
>
> where <commit> is a commit on 'master' (or 'maint' or an even older
> maintenance track, if the topic is about fixing a bug in a released
> version of Git), and <topic*> are topic branches in flight that can
> be merged to the same integration target ('master', or an older
> maintenance tracks you chose <commit> from).  And keep the number of
> <topic*> to an absolute minimum in order for your changes to work.
>
> Thanks.

Thanks.

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

* Re: [GSoC][PATCH 2/2] t: add test for git refs exists subcommand
  2025-08-21 10:21   ` Patrick Steinhardt
@ 2025-08-22  4:59     ` Meet Soni
  0 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-22  4:59 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, shejialuo

On Thu, 21 Aug 2025 at 15:51, Patrick Steinhardt <ps@pks.im> wrote:
>
> On Thu, Aug 21, 2025 at 02:22:46PM +0530, Meet Soni wrote:
> > The new `git refs exists` subcommand must have identical behavior to its
> > predecessor, `git show-ref --exists`. To avoid duplicating the entire
> > test suite, refactor the existing tests into a shareable helper script.
> >
> > Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
> > a new `show-ref-exists-tests.sh` helper. The command under test is
> > parameterized using the `$git_show_ref_exists` variable.
> >
> > Source new helper to both `t1403-show-ref.sh` and the new test file,
>
> s/new/this/, otherwise this reads grammatically wrong to me.
>
> >  test_done
> > diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
> > new file mode 100755
> > index 0000000000..c00d76cc9e
> > --- /dev/null
> > +++ b/t/t1462-refs-exists.sh
> > @@ -0,0 +1,22 @@
> > +#!/bin/sh
> > +
> > +test_description='refs exists'
> > +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> > +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> > +
> > +. ./test-lib.sh
> > +
> > +git_show_ref_exists='git refs exists'
> > +
> > +test_expect_success setup '
> > +     test_commit --annotate A &&
> > +     git checkout -b side &&
> > +     test_commit --annotate B &&
> > +     git checkout main &&
> > +     test_commit C &&
> > +     git branch B A^0
> > +'
>
> It's a bit weird that this setup needs to be replicated. I guess it
> comes from the fact that t1403 also has a bunch of other tests for
> git-show-ref(1) that are irrelevant to existence checks.
>
> How about we instead split out the existence-checks in t1403 into a
> separate test suite first and then pull out the whole logic from it in a
> subsequent commit so that we can also share the setup?
>
Thanks for the review. You're right, splitting the test commit into two is
cleaner. I'll make that change and send out a v2 shortly.

> Patrick

Thanks,
Meet.

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

* [GSoC][PATCH v2 0/4] Add refs exists subcommand
  2025-08-21  8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
                   ` (3 preceding siblings ...)
  2025-08-21 16:01 ` Junio C Hamano
@ 2025-08-23  6:00 ` Meet Soni
  2025-08-23  6:00   ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
                     ` (5 more replies)
  4 siblings, 6 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23  6:00 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

This series introduces `git refs exists` as a modern replacement for
`git show-ref --exists`, continuing the effort to consolidate commands
under the `git refs` namespace.

Changes in v2:
  - v1 was based on the "next" branch as this series required a couple
    of commits merged in it, but as those commits are now completely
    merged into the master branch, I've rebased the v2 onto master
    branch.

  - split the test commit to make the setup shareable.

Meet Soni (4):
  builtin/refs: add 'exists' subcommand
  t1403: split 'show-ref --exists' tests into a separate file
  t1422: refactor tests to be shareable
  t: add test for git refs exists subcommand

 Documentation/git-refs.adoc |  7 ++++
 builtin/refs.c              | 48 +++++++++++++++++++++++
 t/meson.build               |  4 +-
 t/show-ref-exists-tests.sh  | 76 +++++++++++++++++++++++++++++++++++++
 t/t1403-show-ref.sh         | 65 -------------------------------
 t/t1422-show-ref-exists.sh  |  9 +++++
 t/t1462-refs-exists.sh      | 10 +++++
 7 files changed, 153 insertions(+), 66 deletions(-)
 create mode 100644 t/show-ref-exists-tests.sh
 create mode 100755 t/t1422-show-ref-exists.sh
 create mode 100755 t/t1462-refs-exists.sh

Range-diff against v1:
 1:  3fe68ee250 <  -:  ---------- bloom: optimize multiple pathspec items in revision
 2:  36554bf51a <  -:  ---------- commit: convert pop_most_recent_commit() to prio_queue
 3:  304f06e0c0 <  -:  ---------- commit: use prio_queue_replace() in pop_most_recent_commit(),MIME-Version: 1.0
 4:  e436bc94f3 <  -:  ---------- prio-queue: add prio_queue_replace()
 5:  c7a5d9a13c <  -:  ---------- Revert "Merge branch 'rs/pop-recent-commit-with-prio-queue' into next"
 6:  d66d5bfc41 <  -:  ---------- archive: flush deflate stream until Z_STREAM_END
 7:  5297b08916 <  -:  ---------- Revert "Merge branch 'jt/archive-zip-deflate-fix' into next"
 8:  19623eb97e <  -:  ---------- doc: factor out common option
 9:  69c207dc45 <  -:  ---------- builtin/for-each-ref: align usage string with the man page
10:  6eeb1c070a <  -:  ---------- builtin/for-each-ref: factor out core logic into a helper
11:  eecccfe98b <  -:  ---------- builtin/refs: add list subcommand
12:  aa91c5c570 <  -:  ---------- t6300: refactor tests to be shareable
13:  fed66d91c0 <  -:  ---------- t: add test for git refs list subcommand
14:  9bb4abe6cd <  -:  ---------- combine-diff: zero memory used for callback filepairs
15:  2a43e0e550 <  -:  ---------- within_depth: fix return for empty path
16:  a1dfa5448d <  -:  ---------- diff: teach tree-diff a max-depth parameter
17:  b55e6d36eb <  -:  ---------- diff: ensure consistent diff behavior with ignore options
18:  fe54b9ef02 <  -:  ---------- parse-options: refactor flags for usage_with_options_internal
19:  129b3632f3 <  -:  ---------- builtin: also setup gently for --help-all
20:  e1d3d61a45 <  -:  ---------- diff: --no-index should ignore the worktree
21:  621ce9c1c6 <  -:  ---------- git-jump: make `diff` work with filenames containing spaces
22:  9a49aef8dc <  -:  ---------- environment: remove the global variable 'merge_log_config'
23:  22d421fed9 <  -:  ---------- builtin/fmt-merge-msg: stop depending on 'the_repository'
24:  f81a574f59 <  -:  ---------- doc: test linkgit macros for well-formedness
25:  63d33eb7f6 <  -:  ---------- doc: check well-formedness of delimited sections
26:  ed26022094 <  -:  ---------- doc: check for absence of multiple terms in each entry of desc list
27:  03a353bb97 <  -:  ---------- doc: check for absence of the form --[no-]parameter
28:  93203872d7 <  -:  ---------- doc:git-for-each-ref: fix styling and typos
29:  84f3d6e11e <  -:  ---------- doc lint: check that synopsis manpages have synopsis inlines
30:  741f36c7d9 <  -:  ---------- docs: remove stray bracket from git-clone synopsis
31:  83d64df8d5 <  -:  ---------- t7005: use modern test style
32:  a9c4141abb <  -:  ---------- t7005: stop abusing --exec-path
33:  a60203a015 <  -:  ---------- t7005: sanitize test environment for subsequent tests
34:  7d4a5fef7d <  -:  ---------- count-objects: document count-objects pack
35:  3481cb7dfd <  -:  ---------- commit-graph: stop using `the_hash_algo` via macros
36:  e45402bb19 <  -:  ---------- commit-graph: store the hash algorithm instead of its length
37:  f1141b4391 <  -:  ---------- commit-graph: refactor `parse_commit_graph()` to take a repository
38:  89cc9b9adf <  -:  ---------- commit-graph: stop using `the_hash_algo`
39:  ddacfc7466 <  -:  ---------- commit-graph: stop using `the_repository`
40:  7be9e410b2 <  -:  ---------- commit-graph: stop passing in redundant repository
41:  cab69db9c3 <  -:  ---------- t/t1517: mark tests that fail with GIT_TEST_INSTALLED
42:  ab94bb8000 <  -:  ---------- repo: declare the repo command
43:  9adb8a7fd1 <  -:  ---------- repo: add the field references.format
44:  acf2669b54 <  -:  ---------- repo: add the field layout.bare
45:  e52cd654c9 <  -:  ---------- repo: add the field layout.shallow
46:  a81224d128 <  -:  ---------- repo: add the --format flag
47:  d59b2a3793 <  -:  ---------- Revert "Merge branch 'ad/t1517-short-help-tests-fix' into next"
48:  5643b59dea !  1:  d1fa4e927e builtin/refs: add 'exists' subcommand
    @@ Commit message
         builtin/refs: add 'exists' subcommand
     
         As part of the ongoing effort to consolidate reference handling,
    -    introduce a new `exists` subcommand. This command provides the same
    +    introduce `exists` subcommand. This command provides the same
         functionality and exit-code behavior as `git show-ref --exists`, serving
         as its modern replacement.
     
    @@ Commit message
         `git refs list`, where sharing the larger implementation of
         `for-each-ref` was necessary.
     
    -    Documentation for the new subcommand is also added to the `git-refs(1)`
    +    Documentation for this subcommand is also added to the `git-refs(1)`
         man page.
     
         Mentored-by: Patrick Steinhardt <ps@pks.im>
    @@ Documentation/git-refs.adoc
     @@ Documentation/git-refs.adoc: git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
      		   [--contains[=<object>]] [--no-contains[=<object>]]
      		   [(--exclude=<pattern>)...] [--start-after=<marker>]
    - 		   [ --stdin | (<pattern>...)]
    + 		   [ --stdin | <pattern>... ]
     +git refs exists <ref>
      
      DESCRIPTION
    @@ builtin/refs.c: static int cmd_refs_list(int argc, const char **argv, const char
     +	unsigned int unused_type;
     +	int failure_errno = 0;
     +	const char *ref;
    -+
    ++	int ret = 0;
     +	const char * const exists_usage[] = {
     +		REFS_EXISTS_USAGE,
     +		NULL,
    @@ builtin/refs.c: static int cmd_refs_list(int argc, const char **argv, const char
     +	};
     +
     +	argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
    -+	if (!argc)
    -+		die("'git refs exists' requires a reference");
    ++	if (argc != 1)
    ++		die(_("'git refs exists' requires a reference"));
     +
     +	ref = *argv++;
    -+	if (*argv)
    -+		die("'git refs exists' requires exactly one reference");
    -+
     +	if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
     +			      &unused_oid, &unused_referent, &unused_type,
     +			      &failure_errno)) {
     +		if (failure_errno == ENOENT || failure_errno == EISDIR) {
     +			error(_("reference does not exist"));
    -+			return 2;
    ++			ret = 2;
     +		} else {
     +			errno = failure_errno;
     +			error_errno(_("failed to look up reference"));
    -+			return 1;
    ++			ret = 1;
     +		}
    ++
    ++		goto out;
     +	}
     +
    ++out:
     +	strbuf_release(&unused_referent);
    -+	return 0;
    ++	return ret;
     +}
     +
      int cmd_refs(int argc,
 -:  ---------- >  2:  f1dfafe6c9 t1403: split 'show-ref --exists' tests into a separate file
49:  e14bd088bd !  3:  a2a65c428c t: add test for git refs exists subcommand
    @@ Metadata
     Author: Meet Soni <meetsoni3017@gmail.com>
     
      ## Commit message ##
    -    t: add test for git refs exists subcommand
    +    t1422: refactor tests to be shareable
     
    -    The new `git refs exists` subcommand must have identical behavior to its
    -    predecessor, `git show-ref --exists`. To avoid duplicating the entire
    -    test suite, refactor the existing tests into a shareable helper script.
    +    In preparation for adding tests for the `git refs exists` command,
    +    refactor the existing t1422 test suite to make its logic shareable.
     
    -    Extract the tests for the `--exists` flag from `t1403-show-ref.sh` into
    -    a new `show-ref-exists-tests.sh` helper. The command under test is
    -    parameterized using the `$git_show_ref_exists` variable.
    +    Move the core test logic from `t1422-show-ref-exists.sh` to
    +    `show-ref-exists-tests.sh` file. Inside this script, replace hardcoded
    +    calls to "git show-ref --exists" with the `$git_show_ref_exists`
    +    variable.
     
    -    Source new helper to both `t1403-show-ref.sh` and the new test file,
    -    `t1462-refs-exists.sh`, ensuring both commands are verified against the
    -    same comprehensive test suite.
    +    The original `t1422-show-ref-exists.sh` script now becomes a simple
    +    "driver". It is responsible for setting the default value of the
    +    variable and then sourcing the test library.
    +
    +    This structure follows an established pattern for sharing tests and
    +    prepares the test suite for the `refs exists` tests to be added in a
    +    subsequent commit.
     
         Mentored-by: Patrick Steinhardt <ps@pks.im>
         Mentored-by: shejialuo <shejialuo@gmail.com>
         Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
     
    - ## t/meson.build ##
    -@@ t/meson.build: integration_tests = [
    -   't1451-fsck-buffer.sh',
    -   't1460-refs-migrate.sh',
    -   't1461-refs-list.sh',
    -+  't1462-refs-exists.sh',
    -   't1500-rev-parse.sh',
    -   't1501-work-tree.sh',
    -   't1502-rev-parse-parseopt.sh',
    -@@ t/meson.build: if perl.found() and time.found()
    -       timeout: 0,
    -     )
    -   endforeach
    --endif
    - \ No newline at end of file
    -+endif
    -
      ## t/show-ref-exists-tests.sh (new) ##
     @@
     +git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
    ++test_expect_success setup '
    ++	test_commit --annotate A &&
    ++	git checkout -b side &&
    ++	test_commit --annotate B &&
    ++	git checkout main &&
    ++	test_commit C &&
    ++	git branch B A^0
    ++'
     +
     +test_expect_success '--exists with existing reference' '
     +	${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    @@ t/show-ref-exists-tests.sh (new)
     +	git rev-parse HEAD >.git/FETCH_HEAD &&
     +	${git_show_ref_exists} FETCH_HEAD
     +'
    ++
    ++test_done
     
    - ## t/t1403-show-ref.sh ##
    -@@ t/t1403-show-ref.sh: test_expect_success 'show-ref sub-modes are mutually exclusive' '
    - 	grep "cannot be used together" err
    - '
    + ## t/t1422-show-ref-exists.sh (mode change 100644 => 100755) ##
    +@@ t/t1422-show-ref-exists.sh: export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    + . ./test-lib.sh
      
    +-test_expect_success setup '
    +-	test_commit --annotate A &&
    +-	git checkout -b side &&
    +-	test_commit --annotate B &&
    +-	git checkout main &&
    +-	test_commit C &&
    +-	git branch B A^0
    +-'
    +-
     -test_expect_success '--exists with existing reference' '
     -	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
     -'
    @@ t/t1403-show-ref.sh: test_expect_success 'show-ref sub-modes are mutually exclus
     -	git show-ref --exists FETCH_HEAD
     -'
     -
    +-test_done
     +. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
    - test_done
    -
    - ## t/t1462-refs-exists.sh (new) ##
    -@@
    -+#!/bin/sh
    -+
    -+test_description='refs exists'
    -+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    -+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    -+
    -+. ./test-lib.sh
    -+
    -+git_show_ref_exists='git refs exists'
    -+
    -+test_expect_success setup '
    -+	test_commit --annotate A &&
    -+	git checkout -b side &&
    -+	test_commit --annotate B &&
    -+	git checkout main &&
    -+	test_commit C &&
    -+	git branch B A^0
    -+'
    -+
    -+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
    -+
    -+test_done
 -:  ---------- >  4:  e92da499b5 t: add test for git refs exists subcommand
-- 
2.34.1


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

* [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
@ 2025-08-23  6:00   ` Meet Soni
  2025-08-23  6:00   ` [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23  6:00 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

As part of the ongoing effort to consolidate reference handling,
introduce `exists` subcommand. This command provides the same
functionality and exit-code behavior as `git show-ref --exists`, serving
as its modern replacement.

The logic for `show-ref --exists` is minimal. Rather than creating a
shared helper function which would be overkill for ~20 lines of code,
its implementation is intentionally duplicated here. This contrasts with
`git refs list`, where sharing the larger implementation of
`for-each-ref` was necessary.

Documentation for this subcommand is also added to the `git-refs(1)`
man page.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 Documentation/git-refs.adoc |  7 ++++++
 builtin/refs.c              | 48 +++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index e608980711..5d2032b318 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
 		   [--contains[=<object>]] [--no-contains[=<object>]]
 		   [(--exclude=<pattern>)...] [--start-after=<marker>]
 		   [ --stdin | <pattern>... ]
+git refs exists <ref>
 
 DESCRIPTION
 -----------
@@ -38,6 +39,12 @@ list::
 	formatting, and sorting. This subcommand is an alias for
 	linkgit:git-for-each-ref[1] and offers identical functionality.
 
+exists::
+	Check whether the given reference exists. Returns an exit code of 0 if
+	it does, 2 if it is missing, and 1 in case looking up the reference
+	failed with an error other than the reference being missing. This does
+	not verify whether the reference resolves to an actual object.
+
 OPTIONS
 -------
 
diff --git a/builtin/refs.c b/builtin/refs.c
index 76224feba4..91548783b7 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -7,6 +7,7 @@
 #include "strbuf.h"
 #include "worktree.h"
 #include "for-each-ref.h"
+#include "refs/refs-internal.h"
 
 #define REFS_MIGRATE_USAGE \
 	N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -14,6 +15,9 @@
 #define REFS_VERIFY_USAGE \
 	N_("git refs verify [--strict] [--verbose]")
 
+#define REFS_EXISTS_USAGE \
+	N_("git refs exists <ref>")
+
 static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
 			    struct repository *repo UNUSED)
 {
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
 	return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
 }
 
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+			   struct repository *repo UNUSED)
+{
+	struct strbuf unused_referent = STRBUF_INIT;
+	struct object_id unused_oid;
+	unsigned int unused_type;
+	int failure_errno = 0;
+	const char *ref;
+	int ret = 0;
+	const char * const exists_usage[] = {
+		REFS_EXISTS_USAGE,
+		NULL,
+	};
+	struct option options[] = {
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+	if (argc != 1)
+		die(_("'git refs exists' requires a reference"));
+
+	ref = *argv++;
+	if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+			      &unused_oid, &unused_referent, &unused_type,
+			      &failure_errno)) {
+		if (failure_errno == ENOENT || failure_errno == EISDIR) {
+			error(_("reference does not exist"));
+			ret = 2;
+		} else {
+			errno = failure_errno;
+			error_errno(_("failed to look up reference"));
+			ret = 1;
+		}
+
+		goto out;
+	}
+
+out:
+	strbuf_release(&unused_referent);
+	return ret;
+}
+
 int cmd_refs(int argc,
 	     const char **argv,
 	     const char *prefix,
@@ -122,6 +168,7 @@ int cmd_refs(int argc,
 		REFS_MIGRATE_USAGE,
 		REFS_VERIFY_USAGE,
 		"git refs list " COMMON_USAGE_FOR_EACH_REF,
+		REFS_EXISTS_USAGE,
 		NULL,
 	};
 	parse_opt_subcommand_fn *fn = NULL;
@@ -129,6 +176,7 @@ int cmd_refs(int argc,
 		OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
 		OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
 		OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+		OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
 		OPT_END(),
 	};
 
-- 
2.34.1


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

* [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
  2025-08-23  6:00   ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-23  6:00   ` Meet Soni
  2025-08-23  6:00   ` [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable Meet Soni
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23  6:00 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

The test file for git-show-ref(1), `t1403-show-ref.sh`, contains a group
of tests for the '--exists' flag. To improve organization and to prepare
for refactoring these tests to be shareable, move the '--exists' tests
and their corresponding setup logic into a self-contained test suite,
`t1422-show-ref-exists.sh`.

This is a pure code-movement refactoring with no change in test coverage
or behavior.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/meson.build              |  3 +-
 t/t1403-show-ref.sh        | 65 -----------------------------
 t/t1422-show-ref-exists.sh | 83 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 66 deletions(-)
 create mode 100644 t/t1422-show-ref-exists.sh

diff --git a/t/meson.build b/t/meson.build
index daf01fb5d0..4d6bc3d38e 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -205,6 +205,7 @@ integration_tests = [
   't1419-exclude-refs.sh',
   't1420-lost-found.sh',
   't1421-reflog-write.sh',
+  't1422-show-ref-exists.sh',
   't1430-bad-ref-name.sh',
   't1450-fsck.sh',
   't1451-fsck-buffer.sh',
@@ -1216,4 +1217,4 @@ if perl.found() and time.found()
       timeout: 0,
     )
   endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..36c903ca19 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,4 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
 	grep "cannot be used together" err
 '
 
-test_expect_success '--exists with existing reference' '
-	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
-	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
-	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
-	grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
-	git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
-	test_when_finished "git update-ref -d refs/heads/bad...name" &&
-	new_oid=$(git rev-parse HEAD) &&
-	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
-	git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
-	test_when_finished "git symbolic-ref -d refs/symref" &&
-	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
-	git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
-	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
-	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
-	git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
-	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
-	tree_oid=$(git rev-parse HEAD^{tree}) &&
-	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
-	cat >expect <<-EOF &&
-	error: reference does not exist
-	EOF
-	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
-	test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
-	test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
-	test_when_finished "rm .git/FETCH_HEAD" &&
-	git rev-parse HEAD >.git/FETCH_HEAD &&
-	git show-ref --exists FETCH_HEAD
-'
-
 test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
new file mode 100644
index 0000000000..0eccb2dce1
--- /dev/null
+++ b/t/t1422-show-ref-exists.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+test_description='show-ref --exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	test_commit --annotate A &&
+	git checkout -b side &&
+	test_commit --annotate B &&
+	git checkout main &&
+	test_commit C &&
+	git branch B A^0
+'
+
+test_expect_success '--exists with existing reference' '
+	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+	grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+	git show-ref --exists HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+	test_when_finished "git update-ref -d refs/heads/bad...name" &&
+	new_oid=$(git rev-parse HEAD) &&
+	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+	git show-ref --exists refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+	test_when_finished "git symbolic-ref -d refs/symref" &&
+	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+	git show-ref --exists refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	git show-ref --exists refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	git show-ref --exists refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+	tree_oid=$(git rev-parse HEAD^{tree}) &&
+	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	git show-ref --exists refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+	cat >expect <<-EOF &&
+	error: reference does not exist
+	EOF
+	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
+	test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+	test_expect_code 2 git show-ref --exists FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+	test_when_finished "rm .git/FETCH_HEAD" &&
+	git rev-parse HEAD >.git/FETCH_HEAD &&
+	git show-ref --exists FETCH_HEAD
+'
+
+test_done
-- 
2.34.1


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

* [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
  2025-08-23  6:00   ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
  2025-08-23  6:00   ` [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
@ 2025-08-23  6:00   ` Meet Soni
  2025-08-24 16:58     ` Patrick Steinhardt
  2025-08-23  6:00   ` [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand Meet Soni
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: Meet Soni @ 2025-08-23  6:00 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

In preparation for adding tests for the `git refs exists` command,
refactor the existing t1422 test suite to make its logic shareable.

Move the core test logic from `t1422-show-ref-exists.sh` to
`show-ref-exists-tests.sh` file. Inside this script, replace hardcoded
calls to "git show-ref --exists" with the `$git_show_ref_exists`
variable.

The original `t1422-show-ref-exists.sh` script now becomes a simple
"driver". It is responsible for setting the default value of the
variable and then sourcing the test library.

This structure follows an established pattern for sharing tests and
prepares the test suite for the `refs exists` tests to be added in a
subsequent commit.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/show-ref-exists-tests.sh | 76 ++++++++++++++++++++++++++++++++++++++
 t/t1422-show-ref-exists.sh | 76 +-------------------------------------
 2 files changed, 77 insertions(+), 75 deletions(-)
 create mode 100644 t/show-ref-exists-tests.sh
 mode change 100644 => 100755 t/t1422-show-ref-exists.sh

diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..2c29643573
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,76 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+test_expect_success setup '
+	test_commit --annotate A &&
+	git checkout -b side &&
+	test_commit --annotate B &&
+	git checkout main &&
+	test_commit C &&
+	git branch B A^0
+'
+
+test_expect_success '--exists with existing reference' '
+	${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+	test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+	test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+	grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+	${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+	test_when_finished "git update-ref -d refs/heads/bad...name" &&
+	new_oid=$(git rev-parse HEAD) &&
+	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+	test_when_finished "git symbolic-ref -d refs/symref" &&
+	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+	${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+	tree_oid=$(git rev-parse HEAD^{tree}) &&
+	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+	cat >expect <<-EOF &&
+	error: reference does not exist
+	EOF
+	test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+	test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+	test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+	test_when_finished "rm .git/FETCH_HEAD" &&
+	git rev-parse HEAD >.git/FETCH_HEAD &&
+	${git_show_ref_exists} FETCH_HEAD
+'
+
+test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
old mode 100644
new mode 100755
index 0eccb2dce1..fdca3f16c8
--- a/t/t1422-show-ref-exists.sh
+++ b/t/t1422-show-ref-exists.sh
@@ -6,78 +6,4 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
-test_expect_success setup '
-	test_commit --annotate A &&
-	git checkout -b side &&
-	test_commit --annotate B &&
-	git checkout main &&
-	test_commit C &&
-	git branch B A^0
-'
-
-test_expect_success '--exists with existing reference' '
-	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
-	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
-	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
-	grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
-	git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
-	test_when_finished "git update-ref -d refs/heads/bad...name" &&
-	new_oid=$(git rev-parse HEAD) &&
-	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
-	git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
-	test_when_finished "git symbolic-ref -d refs/symref" &&
-	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
-	git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
-	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
-	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
-	git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
-	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
-	tree_oid=$(git rev-parse HEAD^{tree}) &&
-	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
-	cat >expect <<-EOF &&
-	error: reference does not exist
-	EOF
-	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
-	test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
-	test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
-	test_when_finished "rm .git/FETCH_HEAD" &&
-	git rev-parse HEAD >.git/FETCH_HEAD &&
-	git show-ref --exists FETCH_HEAD
-'
-
-test_done
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
-- 
2.34.1


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

* [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
                     ` (2 preceding siblings ...)
  2025-08-23  6:00   ` [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable Meet Soni
@ 2025-08-23  6:00   ` Meet Soni
  2025-08-24 16:58   ` [GSoC][PATCH v2 0/4] Add " Patrick Steinhardt
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-23  6:00 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

Add a test script, `t/t1462-refs-exists.sh`, for the `git refs exists`
command.

This script acts as a simple driver, leveraging the shared test library
created in the preceding commit. It works by overriding the
`$git_show_ref_exists` variable to "git refs exists" and then sourcing the
shared library (`t/show-ref-exists-tests.sh`).

This approach ensures that `git refs exists` is tested against the
entire comprehensive test suite of `git show-ref --exists`, verifying
that it acts as a compatible drop-in replacement.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/meson.build          |  1 +
 t/t1462-refs-exists.sh | 10 ++++++++++
 2 files changed, 11 insertions(+)
 create mode 100755 t/t1462-refs-exists.sh

diff --git a/t/meson.build b/t/meson.build
index 4d6bc3d38e..93e9773ec8 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -211,6 +211,7 @@ integration_tests = [
   't1451-fsck-buffer.sh',
   't1460-refs-migrate.sh',
   't1461-refs-list.sh',
+  't1462-refs-exists.sh',
   't1500-rev-parse.sh',
   't1501-work-tree.sh',
   't1502-rev-parse-parseopt.sh',
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..349453c4ca
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
-- 
2.34.1


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

* Re: [GSoC][PATCH v2 0/4] Add refs exists subcommand
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
                     ` (3 preceding siblings ...)
  2025-08-23  6:00   ` [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand Meet Soni
@ 2025-08-24 16:58   ` Patrick Steinhardt
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
  5 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-24 16:58 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, shejialuo, gitster

On Sat, Aug 23, 2025 at 11:30:08AM +0530, Meet Soni wrote:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
> 
> Changes in v2:
>   - v1 was based on the "next" branch as this series required a couple
>     of commits merged in it, but as those commits are now completely
>     merged into the master branch, I've rebased the v2 onto master
>     branch.

Good.

>   - split the test commit to make the setup shareable.

Good, as well.

>     @@ Commit message
>          builtin/refs: add 'exists' subcommand
>      
>          As part of the ongoing effort to consolidate reference handling,
>     -    introduce a new `exists` subcommand. This command provides the same
>     +    introduce `exists` subcommand. This command provides the same
>          functionality and exit-code behavior as `git show-ref --exists`, serving
>          as its modern replacement.

This reads a bit funny now -- I think the previous version was
preferable.

Patrick

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

* Re: [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable
  2025-08-23  6:00   ` [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable Meet Soni
@ 2025-08-24 16:58     ` Patrick Steinhardt
  0 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-08-24 16:58 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, shejialuo, gitster

On Sat, Aug 23, 2025 at 11:30:11AM +0530, Meet Soni wrote:
> diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
> new file mode 100644
> index 0000000000..2c29643573
> --- /dev/null
> +++ b/t/show-ref-exists-tests.sh
> @@ -0,0 +1,76 @@
> +git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
> +test_expect_success setup '

Tiny nit: let's add an empty line between these two lines.

Patrick

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

* [GSoC][PATCH v3 0/4] Add refs exists subcommand
  2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
                     ` (4 preceding siblings ...)
  2025-08-24 16:58   ` [GSoC][PATCH v2 0/4] Add " Patrick Steinhardt
@ 2025-08-26  6:41   ` Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
                       ` (5 more replies)
  5 siblings, 6 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26  6:41 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

This series introduces `git refs exists` as a modern replacement for
`git show-ref --exists`, continuing the effort to consolidate commands
under the `git refs` namespace.

changes in v3:
 - Reverted commit message.
 - nit: added empty line.

Meet Soni (4):
  builtin/refs: add 'exists' subcommand
  t1403: split 'show-ref --exists' tests into a separate file
  t1422: refactor tests to be shareable
  t: add test for git refs exists subcommand

 Documentation/git-refs.adoc |  7 ++++
 builtin/refs.c              | 48 +++++++++++++++++++++++
 t/meson.build               |  4 +-
 t/show-ref-exists-tests.sh  | 77 +++++++++++++++++++++++++++++++++++++
 t/t1403-show-ref.sh         | 65 -------------------------------
 t/t1422-show-ref-exists.sh  |  9 +++++
 t/t1462-refs-exists.sh      | 10 +++++
 7 files changed, 154 insertions(+), 66 deletions(-)
 create mode 100644 t/show-ref-exists-tests.sh
 create mode 100755 t/t1422-show-ref-exists.sh
 create mode 100755 t/t1462-refs-exists.sh

Range-diff against v2:
 1:  19623eb97e <  -:  ---------- doc: factor out common option
 2:  69c207dc45 <  -:  ---------- builtin/for-each-ref: align usage string with the man page
 3:  6eeb1c070a <  -:  ---------- builtin/for-each-ref: factor out core logic into a helper
 4:  eecccfe98b <  -:  ---------- builtin/refs: add list subcommand
 5:  aa91c5c570 <  -:  ---------- t6300: refactor tests to be shareable
 6:  fed66d91c0 <  -:  ---------- t: add test for git refs list subcommand
 7:  b55e6d36eb <  -:  ---------- diff: ensure consistent diff behavior with ignore options
 8:  e1d3d61a45 <  -:  ---------- diff: --no-index should ignore the worktree
 9:  621ce9c1c6 <  -:  ---------- git-jump: make `diff` work with filenames containing spaces
10:  9a49aef8dc <  -:  ---------- environment: remove the global variable 'merge_log_config'
11:  22d421fed9 <  -:  ---------- builtin/fmt-merge-msg: stop depending on 'the_repository'
12:  741f36c7d9 <  -:  ---------- docs: remove stray bracket from git-clone synopsis
13:  1fa68948c3 <  -:  ---------- The second batch
14:  d1fa4e927e !  1:  0c9349fa74 builtin/refs: add 'exists' subcommand
    @@ Commit message
         builtin/refs: add 'exists' subcommand
     
         As part of the ongoing effort to consolidate reference handling,
    -    introduce `exists` subcommand. This command provides the same
    +    introduce a new `exists` subcommand. This command provides the same
         functionality and exit-code behavior as `git show-ref --exists`, serving
         as its modern replacement.
     
    @@ Commit message
         `git refs list`, where sharing the larger implementation of
         `for-each-ref` was necessary.
     
    -    Documentation for this subcommand is also added to the `git-refs(1)`
    +    Documentation for the new subcommand is also added to the `git-refs(1)`
         man page.
     
         Mentored-by: Patrick Steinhardt <ps@pks.im>
15:  f1dfafe6c9 =  2:  d32067af55 t1403: split 'show-ref --exists' tests into a separate file
16:  a2a65c428c !  3:  fb7223ad07 t1422: refactor tests to be shareable
    @@ Commit message
      ## t/show-ref-exists-tests.sh (new) ##
     @@
     +git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
    ++
     +test_expect_success setup '
     +	test_commit --annotate A &&
     +	git checkout -b side &&
17:  e92da499b5 =  4:  75b5ee4ede t: add test for git refs exists subcommand
-- 
2.34.1


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

* [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
@ 2025-08-26  6:41     ` Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26  6:41 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

As part of the ongoing effort to consolidate reference handling,
introduce a new `exists` subcommand. This command provides the same
functionality and exit-code behavior as `git show-ref --exists`, serving
as its modern replacement.

The logic for `show-ref --exists` is minimal. Rather than creating a
shared helper function which would be overkill for ~20 lines of code,
its implementation is intentionally duplicated here. This contrasts with
`git refs list`, where sharing the larger implementation of
`for-each-ref` was necessary.

Documentation for the new subcommand is also added to the `git-refs(1)`
man page.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 Documentation/git-refs.adoc |  7 ++++++
 builtin/refs.c              | 48 +++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index e608980711..5d2032b318 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -18,6 +18,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
 		   [--contains[=<object>]] [--no-contains[=<object>]]
 		   [(--exclude=<pattern>)...] [--start-after=<marker>]
 		   [ --stdin | <pattern>... ]
+git refs exists <ref>
 
 DESCRIPTION
 -----------
@@ -38,6 +39,12 @@ list::
 	formatting, and sorting. This subcommand is an alias for
 	linkgit:git-for-each-ref[1] and offers identical functionality.
 
+exists::
+	Check whether the given reference exists. Returns an exit code of 0 if
+	it does, 2 if it is missing, and 1 in case looking up the reference
+	failed with an error other than the reference being missing. This does
+	not verify whether the reference resolves to an actual object.
+
 OPTIONS
 -------
 
diff --git a/builtin/refs.c b/builtin/refs.c
index 76224feba4..91548783b7 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -7,6 +7,7 @@
 #include "strbuf.h"
 #include "worktree.h"
 #include "for-each-ref.h"
+#include "refs/refs-internal.h"
 
 #define REFS_MIGRATE_USAGE \
 	N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]")
@@ -14,6 +15,9 @@
 #define REFS_VERIFY_USAGE \
 	N_("git refs verify [--strict] [--verbose]")
 
+#define REFS_EXISTS_USAGE \
+	N_("git refs exists <ref>")
+
 static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
 			    struct repository *repo UNUSED)
 {
@@ -113,6 +117,48 @@ static int cmd_refs_list(int argc, const char **argv, const char *prefix,
 	return for_each_ref_core(argc, argv, prefix, repo, refs_list_usage);
 }
 
+static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
+			   struct repository *repo UNUSED)
+{
+	struct strbuf unused_referent = STRBUF_INIT;
+	struct object_id unused_oid;
+	unsigned int unused_type;
+	int failure_errno = 0;
+	const char *ref;
+	int ret = 0;
+	const char * const exists_usage[] = {
+		REFS_EXISTS_USAGE,
+		NULL,
+	};
+	struct option options[] = {
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, prefix, options, exists_usage, 0);
+	if (argc != 1)
+		die(_("'git refs exists' requires a reference"));
+
+	ref = *argv++;
+	if (refs_read_raw_ref(get_main_ref_store(the_repository), ref,
+			      &unused_oid, &unused_referent, &unused_type,
+			      &failure_errno)) {
+		if (failure_errno == ENOENT || failure_errno == EISDIR) {
+			error(_("reference does not exist"));
+			ret = 2;
+		} else {
+			errno = failure_errno;
+			error_errno(_("failed to look up reference"));
+			ret = 1;
+		}
+
+		goto out;
+	}
+
+out:
+	strbuf_release(&unused_referent);
+	return ret;
+}
+
 int cmd_refs(int argc,
 	     const char **argv,
 	     const char *prefix,
@@ -122,6 +168,7 @@ int cmd_refs(int argc,
 		REFS_MIGRATE_USAGE,
 		REFS_VERIFY_USAGE,
 		"git refs list " COMMON_USAGE_FOR_EACH_REF,
+		REFS_EXISTS_USAGE,
 		NULL,
 	};
 	parse_opt_subcommand_fn *fn = NULL;
@@ -129,6 +176,7 @@ int cmd_refs(int argc,
 		OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
 		OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
 		OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
+		OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
 		OPT_END(),
 	};
 
-- 
2.34.1


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

* [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
@ 2025-08-26  6:41     ` Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable Meet Soni
                       ` (3 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26  6:41 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

The test file for git-show-ref(1), `t1403-show-ref.sh`, contains a group
of tests for the '--exists' flag. To improve organization and to prepare
for refactoring these tests to be shareable, move the '--exists' tests
and their corresponding setup logic into a self-contained test suite,
`t1422-show-ref-exists.sh`.

This is a pure code-movement refactoring with no change in test coverage
or behavior.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/meson.build              |  3 +-
 t/t1403-show-ref.sh        | 65 -----------------------------
 t/t1422-show-ref-exists.sh | 83 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 66 deletions(-)
 create mode 100644 t/t1422-show-ref-exists.sh

diff --git a/t/meson.build b/t/meson.build
index daf01fb5d0..4d6bc3d38e 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -205,6 +205,7 @@ integration_tests = [
   't1419-exclude-refs.sh',
   't1420-lost-found.sh',
   't1421-reflog-write.sh',
+  't1422-show-ref-exists.sh',
   't1430-bad-ref-name.sh',
   't1450-fsck.sh',
   't1451-fsck-buffer.sh',
@@ -1216,4 +1217,4 @@ if perl.found() and time.found()
       timeout: 0,
     )
   endforeach
-endif
\ No newline at end of file
+endif
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
index 9da3650e91..36c903ca19 100755
--- a/t/t1403-show-ref.sh
+++ b/t/t1403-show-ref.sh
@@ -228,69 +228,4 @@ test_expect_success 'show-ref sub-modes are mutually exclusive' '
 	grep "cannot be used together" err
 '
 
-test_expect_success '--exists with existing reference' '
-	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
-	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
-	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
-	grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
-	git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
-	test_when_finished "git update-ref -d refs/heads/bad...name" &&
-	new_oid=$(git rev-parse HEAD) &&
-	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
-	git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
-	test_when_finished "git symbolic-ref -d refs/symref" &&
-	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
-	git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
-	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
-	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
-	git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
-	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
-	tree_oid=$(git rev-parse HEAD^{tree}) &&
-	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
-	cat >expect <<-EOF &&
-	error: reference does not exist
-	EOF
-	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
-	test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
-	test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
-	test_when_finished "rm .git/FETCH_HEAD" &&
-	git rev-parse HEAD >.git/FETCH_HEAD &&
-	git show-ref --exists FETCH_HEAD
-'
-
 test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
new file mode 100644
index 0000000000..0eccb2dce1
--- /dev/null
+++ b/t/t1422-show-ref-exists.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+test_description='show-ref --exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	test_commit --annotate A &&
+	git checkout -b side &&
+	test_commit --annotate B &&
+	git checkout main &&
+	test_commit C &&
+	git branch B A^0
+'
+
+test_expect_success '--exists with existing reference' '
+	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+	grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+	git show-ref --exists HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+	test_when_finished "git update-ref -d refs/heads/bad...name" &&
+	new_oid=$(git rev-parse HEAD) &&
+	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+	git show-ref --exists refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+	test_when_finished "git symbolic-ref -d refs/symref" &&
+	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+	git show-ref --exists refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	git show-ref --exists refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	git show-ref --exists refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+	tree_oid=$(git rev-parse HEAD^{tree}) &&
+	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	git show-ref --exists refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+	cat >expect <<-EOF &&
+	error: reference does not exist
+	EOF
+	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
+	test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+	test_expect_code 2 git show-ref --exists FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+	test_when_finished "rm .git/FETCH_HEAD" &&
+	git rev-parse HEAD >.git/FETCH_HEAD &&
+	git show-ref --exists FETCH_HEAD
+'
+
+test_done
-- 
2.34.1


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

* [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
@ 2025-08-26  6:41     ` Meet Soni
  2025-08-26  6:41     ` [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand Meet Soni
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26  6:41 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

In preparation for adding tests for the `git refs exists` command,
refactor the existing t1422 test suite to make its logic shareable.

Move the core test logic from `t1422-show-ref-exists.sh` to
`show-ref-exists-tests.sh` file. Inside this script, replace hardcoded
calls to "git show-ref --exists" with the `$git_show_ref_exists`
variable.

The original `t1422-show-ref-exists.sh` script now becomes a simple
"driver". It is responsible for setting the default value of the
variable and then sourcing the test library.

This structure follows an established pattern for sharing tests and
prepares the test suite for the `refs exists` tests to be added in a
subsequent commit.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/show-ref-exists-tests.sh | 77 ++++++++++++++++++++++++++++++++++++++
 t/t1422-show-ref-exists.sh | 76 +------------------------------------
 2 files changed, 78 insertions(+), 75 deletions(-)
 create mode 100644 t/show-ref-exists-tests.sh
 mode change 100644 => 100755 t/t1422-show-ref-exists.sh

diff --git a/t/show-ref-exists-tests.sh b/t/show-ref-exists-tests.sh
new file mode 100644
index 0000000000..36e8e9df33
--- /dev/null
+++ b/t/show-ref-exists-tests.sh
@@ -0,0 +1,77 @@
+git_show_ref_exists=${git_show_ref_exists:-git show-ref --exists}
+
+test_expect_success setup '
+	test_commit --annotate A &&
+	git checkout -b side &&
+	test_commit --annotate B &&
+	git checkout main &&
+	test_commit C &&
+	git branch B A^0
+'
+
+test_expect_success '--exists with existing reference' '
+	${git_show_ref_exists} refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+'
+
+test_expect_success '--exists with missing reference' '
+	test_expect_code 2 ${git_show_ref_exists} refs/heads/does-not-exist
+'
+
+test_expect_success '--exists does not use DWIM' '
+	test_expect_code 2 ${git_show_ref_exists} $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
+	grep "reference does not exist" err
+'
+
+test_expect_success '--exists with HEAD' '
+	${git_show_ref_exists} HEAD
+'
+
+test_expect_success '--exists with bad reference name' '
+	test_when_finished "git update-ref -d refs/heads/bad...name" &&
+	new_oid=$(git rev-parse HEAD) &&
+	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/bad...name
+'
+
+test_expect_success '--exists with arbitrary symref' '
+	test_when_finished "git symbolic-ref -d refs/symref" &&
+	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
+	${git_show_ref_exists} refs/symref
+'
+
+test_expect_success '--exists with dangling symref' '
+	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
+	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
+	${git_show_ref_exists} refs/heads/dangling
+'
+
+test_expect_success '--exists with nonexistent object ID' '
+	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/missing-oid
+'
+
+test_expect_success '--exists with non-commit object' '
+	tree_oid=$(git rev-parse HEAD^{tree}) &&
+	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+	${git_show_ref_exists} refs/heads/tree
+'
+
+test_expect_success '--exists with directory fails with generic error' '
+	cat >expect <<-EOF &&
+	error: reference does not exist
+	EOF
+	test_expect_code 2 ${git_show_ref_exists} refs/heads 2>err &&
+	test_cmp expect err
+'
+
+test_expect_success '--exists with non-existent special ref' '
+	test_expect_code 2 ${git_show_ref_exists} FETCH_HEAD
+'
+
+test_expect_success '--exists with existing special ref' '
+	test_when_finished "rm .git/FETCH_HEAD" &&
+	git rev-parse HEAD >.git/FETCH_HEAD &&
+	${git_show_ref_exists} FETCH_HEAD
+'
+
+test_done
diff --git a/t/t1422-show-ref-exists.sh b/t/t1422-show-ref-exists.sh
old mode 100644
new mode 100755
index 0eccb2dce1..fdca3f16c8
--- a/t/t1422-show-ref-exists.sh
+++ b/t/t1422-show-ref-exists.sh
@@ -6,78 +6,4 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 . ./test-lib.sh
 
-test_expect_success setup '
-	test_commit --annotate A &&
-	git checkout -b side &&
-	test_commit --annotate B &&
-	git checkout main &&
-	test_commit C &&
-	git branch B A^0
-'
-
-test_expect_success '--exists with existing reference' '
-	git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
-'
-
-test_expect_success '--exists with missing reference' '
-	test_expect_code 2 git show-ref --exists refs/heads/does-not-exist
-'
-
-test_expect_success '--exists does not use DWIM' '
-	test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err &&
-	grep "reference does not exist" err
-'
-
-test_expect_success '--exists with HEAD' '
-	git show-ref --exists HEAD
-'
-
-test_expect_success '--exists with bad reference name' '
-	test_when_finished "git update-ref -d refs/heads/bad...name" &&
-	new_oid=$(git rev-parse HEAD) &&
-	test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
-	git show-ref --exists refs/heads/bad...name
-'
-
-test_expect_success '--exists with arbitrary symref' '
-	test_when_finished "git symbolic-ref -d refs/symref" &&
-	git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME &&
-	git show-ref --exists refs/symref
-'
-
-test_expect_success '--exists with dangling symref' '
-	test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
-	git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
-	git show-ref --exists refs/heads/dangling
-'
-
-test_expect_success '--exists with nonexistent object ID' '
-	test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/missing-oid
-'
-
-test_expect_success '--exists with non-commit object' '
-	tree_oid=$(git rev-parse HEAD^{tree}) &&
-	test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION &&
-	git show-ref --exists refs/heads/tree
-'
-
-test_expect_success '--exists with directory fails with generic error' '
-	cat >expect <<-EOF &&
-	error: reference does not exist
-	EOF
-	test_expect_code 2 git show-ref --exists refs/heads 2>err &&
-	test_cmp expect err
-'
-
-test_expect_success '--exists with non-existent special ref' '
-	test_expect_code 2 git show-ref --exists FETCH_HEAD
-'
-
-test_expect_success '--exists with existing special ref' '
-	test_when_finished "rm .git/FETCH_HEAD" &&
-	git rev-parse HEAD >.git/FETCH_HEAD &&
-	git show-ref --exists FETCH_HEAD
-'
-
-test_done
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
-- 
2.34.1


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

* [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
                       ` (2 preceding siblings ...)
  2025-08-26  6:41     ` [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable Meet Soni
@ 2025-08-26  6:41     ` Meet Soni
  2025-09-02 11:52     ` [GSoC][PATCH v3 0/4] Add " Patrick Steinhardt
  2025-09-02 16:57     ` Junio C Hamano
  5 siblings, 0 replies; 23+ messages in thread
From: Meet Soni @ 2025-08-26  6:41 UTC (permalink / raw)
  To: git; +Cc: ps, shejialuo, gitster, Meet Soni

Add a test script, `t/t1462-refs-exists.sh`, for the `git refs exists`
command.

This script acts as a simple driver, leveraging the shared test library
created in the preceding commit. It works by overriding the
`$git_show_ref_exists` variable to "git refs exists" and then sourcing the
shared library (`t/show-ref-exists-tests.sh`).

This approach ensures that `git refs exists` is tested against the
entire comprehensive test suite of `git show-ref --exists`, verifying
that it acts as a compatible drop-in replacement.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 t/meson.build          |  1 +
 t/t1462-refs-exists.sh | 10 ++++++++++
 2 files changed, 11 insertions(+)
 create mode 100755 t/t1462-refs-exists.sh

diff --git a/t/meson.build b/t/meson.build
index 4d6bc3d38e..93e9773ec8 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -211,6 +211,7 @@ integration_tests = [
   't1451-fsck-buffer.sh',
   't1460-refs-migrate.sh',
   't1461-refs-list.sh',
+  't1462-refs-exists.sh',
   't1500-rev-parse.sh',
   't1501-work-tree.sh',
   't1502-rev-parse-parseopt.sh',
diff --git a/t/t1462-refs-exists.sh b/t/t1462-refs-exists.sh
new file mode 100755
index 0000000000..349453c4ca
--- /dev/null
+++ b/t/t1462-refs-exists.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+test_description='refs exists'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+git_show_ref_exists='git refs exists'
+. "$TEST_DIRECTORY"/show-ref-exists-tests.sh
-- 
2.34.1


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

* Re: [GSoC][PATCH v3 0/4] Add refs exists subcommand
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
                       ` (3 preceding siblings ...)
  2025-08-26  6:41     ` [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand Meet Soni
@ 2025-09-02 11:52     ` Patrick Steinhardt
  2025-09-02 16:57     ` Junio C Hamano
  5 siblings, 0 replies; 23+ messages in thread
From: Patrick Steinhardt @ 2025-09-02 11:52 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, shejialuo, gitster

On Tue, Aug 26, 2025 at 12:11:06PM +0530, Meet Soni wrote:
> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
> 
> changes in v3:
>  - Reverted commit message.
>  - nit: added empty line.

Thanks, this version looks good to me.

Patrick

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

* Re: [GSoC][PATCH v3 0/4] Add refs exists subcommand
  2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
                       ` (4 preceding siblings ...)
  2025-09-02 11:52     ` [GSoC][PATCH v3 0/4] Add " Patrick Steinhardt
@ 2025-09-02 16:57     ` Junio C Hamano
  5 siblings, 0 replies; 23+ messages in thread
From: Junio C Hamano @ 2025-09-02 16:57 UTC (permalink / raw)
  To: Meet Soni; +Cc: git, ps, shejialuo

Meet Soni <meetsoni3017@gmail.com> writes:

> This series introduces `git refs exists` as a modern replacement for
> `git show-ref --exists`, continuing the effort to consolidate commands
> under the `git refs` namespace.
>
> changes in v3:
>  - Reverted commit message.
>  - nit: added empty line.
>
> Meet Soni (4):
>   builtin/refs: add 'exists' subcommand
>   t1403: split 'show-ref --exists' tests into a separate file
>   t1422: refactor tests to be shareable
>   t: add test for git refs exists subcommand
>
>  Documentation/git-refs.adoc |  7 ++++
>  builtin/refs.c              | 48 +++++++++++++++++++++++
>  t/meson.build               |  4 +-
>  t/show-ref-exists-tests.sh  | 77 +++++++++++++++++++++++++++++++++++++
>  t/t1403-show-ref.sh         | 65 -------------------------------
>  t/t1422-show-ref-exists.sh  |  9 +++++
>  t/t1462-refs-exists.sh      | 10 +++++
>  7 files changed, 154 insertions(+), 66 deletions(-)
>  create mode 100644 t/show-ref-exists-tests.sh
>  create mode 100755 t/t1422-show-ref-exists.sh
>  create mode 100755 t/t1462-refs-exists.sh
>
> Range-diff against v2:
>  1:  19623eb97e <  -:  ---------- doc: factor out common option
>  2:  69c207dc45 <  -:  ---------- builtin/for-each-ref: align usage string with the man page
>  3:  6eeb1c070a <  -:  ---------- builtin/for-each-ref: factor out core logic into a helper
>  4:  eecccfe98b <  -:  ---------- builtin/refs: add list subcommand
>  5:  aa91c5c570 <  -:  ---------- t6300: refactor tests to be shareable
>  6:  fed66d91c0 <  -:  ---------- t: add test for git refs list subcommand
>  7:  b55e6d36eb <  -:  ---------- diff: ensure consistent diff behavior with ignore options
>  8:  e1d3d61a45 <  -:  ---------- diff: --no-index should ignore the worktree
>  9:  621ce9c1c6 <  -:  ---------- git-jump: make `diff` work with filenames containing spaces
> 10:  9a49aef8dc <  -:  ---------- environment: remove the global variable 'merge_log_config'
> 11:  22d421fed9 <  -:  ---------- builtin/fmt-merge-msg: stop depending on 'the_repository'
> 12:  741f36c7d9 <  -:  ---------- docs: remove stray bracket from git-clone synopsis
> 13:  1fa68948c3 <  -:  ---------- The second batch

GitGitGadget and/or range-diff somehow went berserk?

But thanks to it, I now know that the series is built on top of the
second batch ;-)  I was wondering why the patches did not apply
cleanly to a more recent tip of 'master'.

Will queue.  Thanks.

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

end of thread, other threads:[~2025-09-02 16:57 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-21  8:52 [GSoC][PATCH 0/2] Add refs exists subcommand Meet Soni
2025-08-21  8:52 ` [GSoC][PATCH 1/2] builtin/refs: add 'exists' subcommand Meet Soni
2025-08-21 10:21   ` Patrick Steinhardt
2025-08-21  8:52 ` [GSoC][PATCH 2/2] t: add test for git refs exists subcommand Meet Soni
2025-08-21 10:21   ` Patrick Steinhardt
2025-08-22  4:59     ` Meet Soni
2025-08-21 10:21 ` [GSoC][PATCH 0/2] Add " Patrick Steinhardt
2025-08-21 16:01 ` Junio C Hamano
2025-08-22  4:27   ` Meet Soni
2025-08-23  6:00 ` [GSoC][PATCH v2 0/4] " Meet Soni
2025-08-23  6:00   ` [GSoC][PATCH v2 1/4] builtin/refs: add 'exists' subcommand Meet Soni
2025-08-23  6:00   ` [GSoC][PATCH v2 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
2025-08-23  6:00   ` [GSoC][PATCH v2 3/4] t1422: refactor tests to be shareable Meet Soni
2025-08-24 16:58     ` Patrick Steinhardt
2025-08-23  6:00   ` [GSoC][PATCH v2 4/4] t: add test for git refs exists subcommand Meet Soni
2025-08-24 16:58   ` [GSoC][PATCH v2 0/4] Add " Patrick Steinhardt
2025-08-26  6:41   ` [GSoC][PATCH v3 " Meet Soni
2025-08-26  6:41     ` [GSoC][PATCH v3 1/4] builtin/refs: add 'exists' subcommand Meet Soni
2025-08-26  6:41     ` [GSoC][PATCH v3 2/4] t1403: split 'show-ref --exists' tests into a separate file Meet Soni
2025-08-26  6:41     ` [GSoC][PATCH v3 3/4] t1422: refactor tests to be shareable Meet Soni
2025-08-26  6:41     ` [GSoC][PATCH v3 4/4] t: add test for git refs exists subcommand Meet Soni
2025-09-02 11:52     ` [GSoC][PATCH v3 0/4] Add " Patrick Steinhardt
2025-09-02 16:57     ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).