From: Meet Soni <meetsoni3017@gmail•com>
To: git@vger•kernel.org
Cc: ps@pks•im, shejialuo@gmail•com, karthik.188@gmail•com,
Meet Soni <meetsoni3017@gmail•com>,
Junio C Hamano <gitster@pobox•com>,
John Cai <johncai86@gmail•com>
Subject: [GSoC][RFC PATCH 1/2] builtin/refs: add list subcommand
Date: Fri, 27 Jun 2025 13:19:33 +0530 [thread overview]
Message-ID: <20250627074934.1761897-2-meetsoni3017@gmail.com> (raw)
In-Reply-To: <20250627074934.1761897-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`.
For now, cmd_refs_list is effectively a copy of cmd_for_each_ref,
allowing us to reuse the existing filtering and formatting logic while
avoiding any backward compatibility issues. The core implementation
continues to reside in shared modules.
This duplication is temporary and intentional: future enhancements will
be added exclusively to `git refs list`, providing a gradual path
forward without disrupting existing workflows.
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-refs.adoc | 95 +++++++++++++++++++++++++++++++
builtin/refs.c | 110 ++++++++++++++++++++++++++++++++++++
2 files changed, 205 insertions(+)
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index 4d6dc994f9..d8f81eaabd 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 uses the same core logic as
+ linkgit:git-for-each-ref[1] and offers equivalent functionality.
+
OPTIONS
-------
@@ -57,6 +69,89 @@ 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':
+
+<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.
+
+
KNOWN LIMITATIONS
-----------------
diff --git a/builtin/refs.c b/builtin/refs.c
index 998d2a2c1c..70e1757791 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,104 @@ 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 ref_sorting *sorting;
+ struct string_list sorting_options = STRING_LIST_INIT_DUP;
+ int icase = 0, include_root_refs = 0, from_stdin = 0;
+ struct ref_filter filter = REF_FILTER_INIT;
+ struct ref_format format = REF_FORMAT_INIT;
+ unsigned int flags = FILTER_REFS_REGULAR;
+ struct strvec vec = STRVEC_INIT;
+ const char * const list_usage[] = {
+ REFS_LIST_USAGE,
+ NULL
+ };
+
+ struct option opts[] = {
+ OPT_BIT('s', "shell", &format.quote_style,
+ N_("quote placeholders suitably for shells"), QUOTE_SHELL),
+ OPT_BIT('p', "perl", &format.quote_style,
+ N_("quote placeholders suitably for perl"), QUOTE_PERL),
+ OPT_BIT(0 , "python", &format.quote_style,
+ N_("quote placeholders suitably for python"), QUOTE_PYTHON),
+ OPT_BIT(0 , "tcl", &format.quote_style,
+ N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
+ OPT_BOOL(0, "omit-empty", &format.array_opts.omit_empty,
+ N_("do not output a newline after empty formatted refs")),
+
+ OPT_GROUP(""),
+ OPT_INTEGER(0, "count", &format.array_opts.max_count, N_("show only <n> matched refs")),
+ OPT_STRING(0, "format", &format.format, N_("format"), N_("format to use for the output")),
+ OPT__COLOR(&format.use_color, N_("respect format colors")),
+ OPT_REF_FILTER_EXCLUDE(&filter),
+ OPT_REF_SORT(&sorting_options),
+ OPT_CALLBACK(0, "points-at", &filter.points_at,
+ N_("object"), N_("print only refs which points at the given object"),
+ parse_opt_object_name),
+ OPT_MERGED(&filter, N_("print only refs that are merged")),
+ OPT_NO_MERGED(&filter, N_("print only refs that are not merged")),
+ OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
+ OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
+ OPT_BOOL(0, "stdin", &from_stdin, N_("read reference patterns from stdin")),
+ OPT_BOOL(0, "include-root-refs", &include_root_refs, N_("also include HEAD ref and pseudorefs")),
+ OPT_END(),
+ };
+
+ format.format = "%(objectname) %(objecttype)\t%(refname)";
+
+ repo_config(repo, git_default_config, NULL);
+
+ /* Default to sorting by refname unless overridden by --sort= */
+ string_list_append(&sorting_options, "refname");
+
+ parse_options(argc, argv, prefix, opts, list_usage, 0);
+ if (format.array_opts.max_count < 0) {
+ error("invalid --count value: `%d'", format.array_opts.max_count);
+ usage_with_options(list_usage, opts);
+ }
+ if (HAS_MULTI_BITS(format.quote_style)) {
+ error("more than one quoting style?");
+ usage_with_options(list_usage, opts);
+ }
+ if (verify_ref_format(&format))
+ usage_with_options(list_usage, opts);
+
+ sorting = ref_sorting_options(&sorting_options);
+ ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
+ filter.ignore_case = icase;
+
+ if (from_stdin) {
+ struct strbuf line = STRBUF_INIT;
+
+ if (argv[0])
+ die(_("unknown arguments supplied with --stdin"));
+
+ while (strbuf_getline(&line, stdin) != EOF)
+ strvec_push(&vec, line.buf);
+
+ strbuf_release(&line);
+
+ /* vec.v is NULL-terminated, just like 'argv'. */
+ filter.name_patterns = vec.v;
+ } else {
+ filter.name_patterns = argv;
+ }
+
+ if (include_root_refs)
+ flags |= FILTER_REFS_ROOT_REFS | FILTER_REFS_DETACHED_HEAD;
+
+ filter.match_as_path = 1;
+ filter_and_format_refs(&filter, flags, sorting, &format);
+
+ ref_filter_clear(&filter);
+ ref_sorting_release(sorting);
+ strvec_clear(&vec);
+ return 0;
+}
+
int cmd_refs(int argc,
const char **argv,
const char *prefix,
@@ -109,12 +217,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
next prev parent reply other threads:[~2025-06-27 7:50 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-27 7:49 [GSoC][RFC PATCH 0/2] Add refs list subcommand Meet Soni
2025-06-27 7:49 ` Meet Soni [this message]
2025-06-27 16:27 ` [GSoC][RFC PATCH 1/2] builtin/refs: add " Jean-Noël Avila
2025-06-27 18:13 ` Junio C Hamano
2025-06-30 4:28 ` Meet Soni
2025-06-29 11:05 ` [PATCH] doc:git-for-each-ref: fix styling and typos Jean-Noël Avila
2025-06-30 15:48 ` Junio C Hamano
2025-06-30 18:55 ` Jean-Noël AVILA
2025-06-27 7:49 ` [GSoC][RFC PATCH 2/2] t: add test for git refs list subcommand Meet Soni
2025-06-27 18:03 ` [GSoC][RFC PATCH 0/2] Add " Junio C Hamano
2025-06-28 8:05 ` shejialuo
2025-06-30 14:05 ` Junio C Hamano
2025-07-06 12:58 ` shejialuo
2025-06-30 3:53 ` Meet Soni
2025-06-30 20:10 ` Junio C Hamano
2025-07-09 13:36 ` Patrick Steinhardt
2025-07-17 7:50 ` [GSoC][RFC PATCH v2 " Meet Soni
2025-07-17 7:50 ` [GSoC][RFC PATCH v2 1/2] builtin/refs: add " Meet Soni
2025-07-17 16:48 ` Eric Sunshine
2025-07-23 5:01 ` Meet Soni
2025-07-17 7:50 ` [GSoC][RFC PATCH v2 2/2] t: add test for git refs " Meet Soni
2025-07-17 21:01 ` Junio C Hamano
2025-07-23 5:17 ` Meet Soni
2025-07-23 15:03 ` Junio C Hamano
2025-07-23 6:43 ` [GSoC][RFC PATCH v3 0/3] Add " Meet Soni
2025-07-23 6:43 ` [GSoC][RFC PATCH v3 1/3] builtin/refs: add " Meet Soni
2025-07-24 5:58 ` Patrick Steinhardt
2025-07-24 16:01 ` Junio C Hamano
2025-07-25 11:10 ` Meet Soni
2025-07-23 6:43 ` [GSoC][RFC PATCH v3 2/3] t6300: refactor tests to be shareable Meet Soni
2025-07-23 6:43 ` [GSoC][RFC PATCH v3 3/3] t: add test for git refs list subcommand Meet Soni
2025-07-31 9:00 ` [GSoC][RFC PATCH v4 0/5] Add " Meet Soni
2025-07-31 9:00 ` [GSoC][RFC PATCH v4 1/5] doc: factor out common option Meet Soni
2025-07-31 9:00 ` [GSoC][RFC PATCH v4 2/5] builtin/for-each-ref: factor out core logic into a helper Meet Soni
2025-08-01 5:54 ` Patrick Steinhardt
2025-08-04 6:34 ` Meet Soni
2025-07-31 9:00 ` [GSoC][RFC PATCH v4 3/5] builtin/refs: add list subcommand Meet Soni
2025-08-01 13:27 ` Phillip Wood
2025-08-01 14:43 ` Junio C Hamano
2025-08-01 15:49 ` Phillip Wood
2025-08-01 17:14 ` Junio C Hamano
2025-08-04 9:28 ` Phillip Wood
2025-08-04 6:32 ` Meet Soni
2025-08-04 9:27 ` Phillip Wood
2025-08-04 15:35 ` Junio C Hamano
2025-07-31 9:00 ` [GSoC][RFC PATCH v4 4/5] t6300: refactor tests to be shareable Meet Soni
2025-07-31 9:00 ` [GSoC][RFC PATCH v4 5/5] t: add test for git refs list subcommand Meet Soni
2025-08-01 5:54 ` [GSoC][RFC PATCH v4 0/5] Add " Patrick Steinhardt
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 0/6] " Meet Soni
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 1/6] doc: factor out common option Meet Soni
2025-08-04 18:34 ` Junio C Hamano
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 2/6] builtin/for-each-ref: align usage string with the man page Meet Soni
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 3/6] builtin/for-each-ref: factor out core logic into a helper Meet Soni
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 4/6] builtin/refs: add list subcommand Meet Soni
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 5/6] t6300: refactor tests to be shareable Meet Soni
2025-08-04 9:22 ` [GSoC][RFC PATCH v5 6/6] t: add test for git refs list subcommand Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 0/6] Add " Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 1/6] doc: factor out common option Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 2/6] builtin/for-each-ref: align usage string with the man page Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 3/6] builtin/for-each-ref: factor out core logic into a helper Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 4/6] builtin/refs: add list subcommand Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 5/6] t6300: refactor tests to be shareable Meet Soni
2025-08-05 9:27 ` [GSoC][PATCH v6 6/6] t: add test for git refs list subcommand Meet Soni
2025-08-05 13:07 ` [GSoC][PATCH v6 0/6] Add " Patrick Steinhardt
2025-08-05 16:12 ` Junio C Hamano
-- strict thread matches above, loose matches on Subject: below --
2025-06-14 7:05 [GSoC][RFC PATCH 0/2] " Meet Soni
2025-06-14 7:05 ` [GSoC][RFC PATCH 1/2] builtin/refs: add " Meet Soni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250627074934.1761897-2-meetsoni3017@gmail.com \
--to=meetsoni3017@gmail$(echo .)com \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
--cc=johncai86@gmail$(echo .)com \
--cc=karthik.188@gmail$(echo .)com \
--cc=ps@pks$(echo .)im \
--cc=shejialuo@gmail$(echo .)com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox