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

[GSoC][RFC PATCH v2 1/2] builtin/refs: add list subcommand

From
Meet Soni <meetsoni3017@gmail.com>
Date
Jul 17, 2025, 07:50 UTC
Message-ID
<20250717075009.26262-2-meetsoni3017@gmail.com>
In-Reply-To
<20250717075009.26262-1-meetsoni3017@gmail.com>

Git's reference management is distributed across multiple commands. As part of an ongoing effort to consolidate and modernize reference handling, introduce a `list` subcommand under the `git refs` umbrella as a replacement for `git for-each-ref`.

Implement `cmd_refs_list` as a thin wrapper around `cmd_for_each_ref` instead of duplicating its logic. Forward all arguments to the existing function to ensure behavior is identical.

Add documentation for the new command. To keep the documentation DRY and consistent with `git-for-each-ref(1)`, refactor the shared command options into a standalone file. Use the AsciiDoc `include::` macro to embed these options in both man pages.

This prevents duplication in both code and documentation, ensuring that `refs list` benefits from any future fixes to the underlying `for-each-ref` machinery and its shared documentation.

Mentored-by: Patrick Steinhardt <ps@pks.im>
Mentored-by: shejialuo <shejialuo@gmail.com>
Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Meet Soni <meetsoni3017@gmail.com>
---
 Documentation/git-for-each-ref.adoc  | 80 +---------------------------
 Documentation/git-refs.adoc          | 16 ++++++
 Documentation/refs-list-options.adoc | 80 ++++++++++++++++++++++++++++
 builtin/for-each-ref.c               | 24 +++++++--
 builtin/refs.c                       | 35 ++++++++++++
 5 files changed, 152 insertions(+), 83 deletions(-)
 create mode 100644 Documentation/refs-list-options.adoc
diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc
index 5ef89fc0fe..f7bbc1902a 100644
--- a/Documentation/git-for-each-ref.adoc
+++ b/Documentation/git-for-each-ref.adoc
@@ -28,85 +28,7 @@ host language allowing their direct evaluation in that language.
 
 OPTIONS
 -------
-<pattern>...::
-	If one or more patterns are given, only refs are shown that
-	match against at least one pattern, either using fnmatch(3) or
-	literally, in the latter case matching completely or from the
-	beginning up to a slash.
-
---stdin::
-	If `--stdin` is supplied, then the list of patterns is read from
-	standard input instead of from the argument list.
-
---count=<count>::
-	By default the command shows all refs that match
-	`<pattern>`.  This option makes it stop after showing
-	that many refs.
-
---sort=<key>::
-	A field name to sort on.  Prefix `-` to sort in
-	descending order of the value.  When unspecified,
-	`refname` is used.  You may use the --sort=<key> option
-	multiple times, in which case the last key becomes the primary
-	key.
-
---format=<format>::
-	A string that interpolates `%(fieldname)` from a ref being shown and
-	the object it points at. In addition, the string literal `%%`
-	renders as `%` and `%xx` - where `xx` are hex digits - renders as
-	the character with hex code `xx`. For example, `%00` interpolates to
-	`\0` (NUL), `%09` to `\t` (TAB), and `%0a` to `\n` (LF).
-+
-When unspecified, `<format>` defaults to `%(objectname) SPC %(objecttype)
-TAB %(refname)`.
-
---color[=<when>]::
-	Respect any colors specified in the `--format` option. The
-	`<when>` field must be one of `always`, `never`, or `auto` (if
-	`<when>` is absent, behave as if `always` was given).
-
---shell::
---perl::
---python::
---tcl::
-	If given, strings that substitute `%(fieldname)`
-	placeholders are quoted as string literals suitable for
-	the specified host language.  This is meant to produce
-	a scriptlet that can directly be `eval`ed.
-
---points-at=<object>::
-	Only list refs which points at the given object.
-
---merged[=<object>]::
-	Only list refs whose tips are reachable from the
-	specified commit (HEAD if not specified).
-
---no-merged[=<object>]::
-	Only list refs whose tips are not reachable from the
-	specified commit (HEAD if not specified).
-
---contains[=<object>]::
-	Only list refs which contain the specified commit (HEAD if not
-	specified).
-
---no-contains[=<object>]::
-	Only list refs which don't contain the specified commit (HEAD
-	if not specified).
-
---ignore-case::
-	Sorting and filtering refs are case insensitive.
-
---omit-empty::
-	Do not print a newline after formatted refs where the format expands
-	to the empty string.
-
---exclude=<pattern>::
-	If one or more patterns are given, only refs which do not match
-	any excluded pattern(s) are shown. Matching is done using the
-	same rules as `<pattern>` above.
-
---include-root-refs::
-	List root refs (HEAD and pseudorefs) apart from regular refs.
+include::refs-list-options.adoc[]
 
 FIELD NAMES
 -----------
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index 4d6dc994f9..ded90f435b 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -11,6 +11,13 @@ SYNOPSIS
 [synopsis]
 git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]
 git refs verify [--strict] [--verbose]
+git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
+	      [(--sort=<key>)...] [--format=<format>]
+	      [--include-root-refs] [ --stdin | <pattern>... ]
+	      [--points-at=<object>]
+	      [--merged[=<object>]] [--no-merged[=<object>]]
+	      [--contains[=<object>]] [--no-contains[=<object>]]
+	      [--exclude=<pattern> ...]
 
 DESCRIPTION
 -----------
@@ -26,6 +33,11 @@ migrate::
 verify::
 	Verify reference database consistency.
 
+list::
+	List references in the repository with support for filtering,
+	formatting, and sorting. This subcommand is an alias for
+	linkgit:git-for-each-ref[1] and offers identical functionality.
+
 OPTIONS
 -------
 
@@ -57,6 +69,10 @@ The following options are specific to 'git refs verify':
 --verbose::
 	When verifying the reference database consistency, be chatty.
 
+The following options are specific to 'git refs list':
+
+include::refs-list-options.adoc[]
+
 KNOWN LIMITATIONS
 -----------------
 
diff --git a/Documentation/refs-list-options.adoc b/Documentation/refs-list-options.adoc
new file mode 100644
index 0000000000..9d6557cdb9
--- /dev/null
+++ b/Documentation/refs-list-options.adoc
@@ -0,0 +1,80 @@
+// Shared options for for-each-ref and refs list
+<pattern>...::
+	If one or more patterns are given, only refs are shown that
+	match against at least one pattern, either using fnmatch(3) or
+	literally, in the latter case matching completely or from the
+	beginning up to a slash.
+
+--stdin::
+	If `--stdin` is supplied, then the list of patterns is read from
+	standard input instead of from the argument list.
+
+--count=<count>::
+	By default the command shows all refs that match
+	`<pattern>`.  This option makes it stop after showing
+	that many refs.
+
+--sort=<key>::
+	A field name to sort on.  Prefix `-` to sort in
+	descending order of the value.  When unspecified,
+	`refname` is used.  You may use the --sort=<key> option
+	multiple times, in which case the last key becomes the primary
+	key.
+
+--format=<format>::
+	A string that interpolates `%(fieldname)` from a ref being shown and
+	the object it points at. In addition, the string literal `%%`
+	renders as `%` and `%xx` - where `xx` are hex digits - renders as
+	the character with hex code `xx`. For example, `%00` interpolates to
+	`\0` (NUL), `%09` to `\t` (TAB), and `%0a` to `\n` (LF).
++
+When unspecified, `<format>` defaults to `%(objectname) SPC %(objecttype)
+TAB %(refname)`.
+
+--color[=<when>]::
+	Respect any colors specified in the `--format` option. The
+	`<when>` field must be one of `always`, `never`, or `auto` (if
+	`<when>` is absent, behave as if `always` was given).
+
+--shell::
+--perl::
+--python::
+--tcl::
+	If given, strings that substitute `%(fieldname)`
+	placeholders are quoted as string literals suitable for
+	the specified host language.  This is meant to produce
+	a scriptlet that can directly be `eval`ed.
+
+--points-at=<object>::
+	Only list refs which points at the given object.
+
+--merged[=<object>]::
+	Only list refs whose tips are reachable from the
+	specified commit (HEAD if not specified).
+
+--no-merged[=<object>]::
+	Only list refs whose tips are not reachable from the
+	specified commit (HEAD if not specified).
+
+--contains[=<object>]::
+	Only list refs which contain the specified commit (HEAD if not
+	specified).
+
+--no-contains[=<object>]::
+	Only list refs which don't contain the specified commit (HEAD
+	if not specified).
+
+--ignore-case::
+	Sorting and filtering refs are case insensitive.
+
+--omit-empty::
+	Do not print a newline after formatted refs where the format expands
+	to the empty string.
+
+--exclude=<pattern>::
+	If one or more patterns are given, only refs which do not match
+	any excluded pattern(s) are shown. Matching is done using the
+	same rules as `<pattern>` above.
+
+--include-root-refs::
+	List root refs (HEAD and pseudorefs) apart from regular refs.
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 3d2207ec77..d7d8279049 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -16,11 +16,27 @@ static char const * const for_each_ref_usage[] = {
 	NULL
 };
 
+#define REFS_LIST_USAGE \
+	N_("git refs list [--count=<count>] [--shell|--perl|--python|--tcl]\n" \
+	   "              [(--sort=<key>)...] [--format=<format>]\n" \
+	   "              [--include-root-refs] [ --stdin | <pattern>... ]\n" \
+	   "              [--points-at=<object>]\n" \
+	   "              [--merged[=<object>]] [--no-merged[=<object>]]\n" \
+	   "              [--contains[=<object>]] [--no-contains[=<object>]]\n" \
+	   "              [--exclude=<pattern> ...]")
+
+static char const * const refs_list_usage[] = {
+	REFS_LIST_USAGE,
+	NULL
+};
+
 int cmd_for_each_ref(int argc,
 		     const char **argv,
 		     const char *prefix,
 		     struct repository *repo)
 {
+	int cmd_is_refs_list = !strcmp(argv[0], "refs list");
+	const char *const *opt_usage = cmd_is_refs_list ? refs_list_usage : for_each_ref_usage;
 	struct ref_sorting *sorting;
 	struct string_list sorting_options = STRING_LIST_INIT_DUP;
 	int icase = 0, include_root_refs = 0, from_stdin = 0;
@@ -67,17 +83,17 @@ int cmd_for_each_ref(int argc,
 	/* Set default (refname) sorting */
 	string_list_append(&sorting_options, "refname");
 
-	parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
+	parse_options(argc, argv, prefix, opts, opt_usage, 0);
 	if (format.array_opts.max_count < 0) {
 		error("invalid --count argument: `%d'", format.array_opts.max_count);
-		usage_with_options(for_each_ref_usage, opts);
+		usage_with_options(opt_usage, opts);
 	}
 	if (HAS_MULTI_BITS(format.quote_style)) {
 		error("more than one quoting style?");
-		usage_with_options(for_each_ref_usage, opts);
+		usage_with_options(opt_usage, opts);
 	}
 	if (verify_ref_format(&format))
-		usage_with_options(for_each_ref_usage, opts);
+		usage_with_options(opt_usage, opts);
 
 	sorting = ref_sorting_options(&sorting_options);
 	ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
diff --git a/builtin/refs.c b/builtin/refs.c
index 998d2a2c1c..41e29d1b5f 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -3,6 +3,7 @@
 #include "config.h"
 #include "fsck.h"
 #include "parse-options.h"
+#include "ref-filter.h"
 #include "refs.h"
 #include "strbuf.h"
 #include "worktree.h"
@@ -13,6 +14,15 @@
 #define REFS_VERIFY_USAGE \
 	N_("git refs verify [--strict] [--verbose]")
 
+#define REFS_LIST_USAGE \
+	N_("git refs list [--count=<count>] [--shell|--perl|--python|--tcl]\n" \
+	   "              [(--sort=<key>)...] [--format=<format>]\n" \
+	   "              [--include-root-refs] [ --stdin | <pattern>... ]\n" \
+	   "              [--points-at=<object>]\n" \
+	   "              [--merged[=<object>]] [--no-merged[=<object>]]\n" \
+	   "              [--contains[=<object>]] [--no-contains[=<object>]]\n" \
+	   "              [--exclude=<pattern> ...]")
+
 static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
 			    struct repository *repo UNUSED)
 {
@@ -101,6 +111,29 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
 	return ret;
 }
 
+static int cmd_refs_list(int argc, const char **argv, const char *prefix,
+		  struct repository *repo)
+{
+	struct strvec args = STRVEC_INIT;
+	const char **args_copy;
+	int ret;
+
+	strvec_push(&args, "refs list");
+
+	for (int i = 1; i < argc; i++)
+		strvec_push(&args, argv[i]);
+
+	CALLOC_ARRAY(args_copy, args.nr + 1);
+	COPY_ARRAY(args_copy, args.v, args.nr);
+
+	ret = cmd_for_each_ref(args.nr, args_copy, prefix, repo);
+
+	strvec_clear(&args);
+	free(args_copy);
+
+	return ret;
+}
+
 int cmd_refs(int argc,
 	     const char **argv,
 	     const char *prefix,
@@ -109,12 +142,14 @@ int cmd_refs(int argc,
 	const char * const refs_usage[] = {
 		REFS_MIGRATE_USAGE,
 		REFS_VERIFY_USAGE,
+		REFS_LIST_USAGE,
 		NULL,
 	};
 	parse_opt_subcommand_fn *fn = NULL;
 	struct option opts[] = {
 		OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate),
 		OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
+		OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
 		OPT_END(),
 	};
 
-- 
2.34.1
Previous: Meet SoniNext: Eric Sunshine
Message 18 of 65 in “Add refs list subcommand”
  1. Meet SoniJun 27, 2025
  2. [GSoC][RFC PATCH 1/2] builtin/refs: add list subcommandMeet Soni, Jun 27, 2025
  3. Jean-Noël AvilaJun 27, 2025
  4. Junio C HamanoJun 27, 2025
  5. Meet SoniJun 30, 2025
  6. doc:git-for-each-ref: fix styling and typosJean-Noël Avila, Jun 29, 2025
  7. Junio C HamanoJun 30, 2025
  8. Jean-Noël AVILAJun 30, 2025
  9. [GSoC][RFC PATCH 2/2] t: add test for git refs list subcommandMeet Soni, Jun 27, 2025
  10. Junio C HamanoJun 27, 2025
  11. shejialuoJun 28, 2025
  12. Junio C HamanoJun 30, 2025
  13. shejialuoJul 6, 2025
  14. Meet SoniJun 30, 2025
  15. Junio C HamanoJun 30, 2025
  16. Patrick SteinhardtJul 9, 2025
  17. [GSoC][RFC PATCH v2 0/2] Add refs list subcommandMeet Soni, Jul 17, 2025
  18. [GSoC][RFC PATCH v2 1/2] builtin/refs: add list subcommandMeet Soni, Jul 17, 2025
  19. Eric SunshineJul 17, 2025
  20. Meet SoniJul 23, 2025
  21. [GSoC][RFC PATCH v2 2/2] t: add test for git refs list subcommandMeet Soni, Jul 17, 2025
  22. Junio C HamanoJul 17, 2025
  23. Meet SoniJul 23, 2025
  24. Junio C HamanoJul 23, 2025
  25. [GSoC][RFC PATCH v3 0/3] Add refs list subcommandMeet Soni, Jul 23, 2025
  26. [GSoC][RFC PATCH v3 1/3] builtin/refs: add list subcommandMeet Soni, Jul 23, 2025
  27. Patrick SteinhardtJul 24, 2025
  28. Junio C HamanoJul 24, 2025
  29. Meet SoniJul 25, 2025
  30. [GSoC][RFC PATCH v3 2/3] t6300: refactor tests to be shareableMeet Soni, Jul 23, 2025
  31. [GSoC][RFC PATCH v3 3/3] t: add test for git refs list subcommandMeet Soni, Jul 23, 2025
  32. [GSoC][RFC PATCH v4 0/5] Add refs list subcommandMeet Soni, Jul 31, 2025
  33. [GSoC][RFC PATCH v4 1/5] doc: factor out common optionMeet Soni, Jul 31, 2025
  34. [GSoC][RFC PATCH v4 2/5] builtin/for-each-ref: factor out core logic into a helperMeet Soni, Jul 31, 2025
  35. Patrick SteinhardtAug 1, 2025
  36. Meet SoniAug 4, 2025
  37. [GSoC][RFC PATCH v4 3/5] builtin/refs: add list subcommandMeet Soni, Jul 31, 2025
  38. Phillip WoodAug 1, 2025
  39. Junio C HamanoAug 1, 2025
  40. Phillip WoodAug 1, 2025
  41. Junio C HamanoAug 1, 2025
  42. Phillip WoodAug 4, 2025
  43. Meet SoniAug 4, 2025
  44. Phillip WoodAug 4, 2025
  45. Junio C HamanoAug 4, 2025
  46. [GSoC][RFC PATCH v4 4/5] t6300: refactor tests to be shareableMeet Soni, Jul 31, 2025
  47. [GSoC][RFC PATCH v4 5/5] t: add test for git refs list subcommandMeet Soni, Jul 31, 2025
  48. Patrick SteinhardtAug 1, 2025
  49. [GSoC][RFC PATCH v5 0/6] Add refs list subcommandMeet Soni, Aug 4, 2025
  50. [GSoC][RFC PATCH v5 1/6] doc: factor out common optionMeet Soni, Aug 4, 2025
  51. Junio C HamanoAug 4, 2025
  52. [GSoC][RFC PATCH v5 2/6] builtin/for-each-ref: align usage string with the man pageMeet Soni, Aug 4, 2025
  53. [GSoC][RFC PATCH v5 3/6] builtin/for-each-ref: factor out core logic into a helperMeet Soni, Aug 4, 2025
  54. [GSoC][RFC PATCH v5 4/6] builtin/refs: add list subcommandMeet Soni, Aug 4, 2025
  55. [GSoC][RFC PATCH v5 5/6] t6300: refactor tests to be shareableMeet Soni, Aug 4, 2025
  56. [GSoC][RFC PATCH v5 6/6] t: add test for git refs list subcommandMeet Soni, Aug 4, 2025
  57. [GSoC][PATCH v6 0/6] Add refs list subcommandMeet Soni, Aug 5, 2025
  58. [GSoC][PATCH v6 1/6] doc: factor out common optionMeet Soni, Aug 5, 2025
  59. [GSoC][PATCH v6 2/6] builtin/for-each-ref: align usage string with the man pageMeet Soni, Aug 5, 2025
  60. [GSoC][PATCH v6 3/6] builtin/for-each-ref: factor out core logic into a helperMeet Soni, Aug 5, 2025
  61. [GSoC][PATCH v6 4/6] builtin/refs: add list subcommandMeet Soni, Aug 5, 2025
  62. [GSoC][PATCH v6 5/6] t6300: refactor tests to be shareableMeet Soni, Aug 5, 2025
  63. [GSoC][PATCH v6 6/6] t: add test for git refs list subcommandMeet Soni, Aug 5, 2025
  64. Patrick SteinhardtAug 5, 2025
  65. Junio C HamanoAug 5, 2025

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

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