* [GSoC][PATCH] builtin/refs: add 'get' subcommand
@ 2025-09-23 10:45 Meet Soni
2025-09-23 16:57 ` Ben Knoble
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Meet Soni @ 2025-09-23 10:45 UTC (permalink / raw)
To: git; +Cc: ps, shejialuo, Meet Soni
While `git-rev-parse(1)` and `git-show-ref(1)` can be used to read
reference values, they have drawbacks for scripting and discoverability.
`rev-parse` performs DWIM expansion which is unpredictable for scripts,
and `show-ref --verify` is difficult to discover and cannot read the
direct target of a symbolic reference.
To address this, introduce a new plumbing command, `git refs get <ref>`.
This new command provides three key advantages:
- It requires an exact refname and does not perform expansion, making
it safer and more predictable for scripting.
- Its name clearly states its purpose and it lives in the logical `git
refs` namespace, unlike the `--verify` flag which lives in
`git-show-ref`.
- It provides a clean, dedicated way to read the direct target of a
symbolic reference (e.g., `HEAD`) without recursively dereferencing
it to an object ID.
Add documentation for the new subcommand to the `git-refs(1)` man page
and a comprehensive test suite to verify its behavior.
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 | 43 ++++++++++++++++++++++++
t/meson.build | 1 +
t/t1464-refs-get.sh | 66 +++++++++++++++++++++++++++++++++++++
4 files changed, 117 insertions(+)
create mode 100755 t/t1464-refs-get.sh
diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
index bfa9b3ea2d..f07fe8c864 100644
--- a/Documentation/git-refs.adoc
+++ b/Documentation/git-refs.adoc
@@ -19,6 +19,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
[(--exclude=<pattern>)...] [--start-after=<marker>]
[ --stdin | (<pattern>...)]
git refs exists <ref>
+git refs get <ref>
DESCRIPTION
-----------
@@ -45,6 +46,12 @@ exists::
failed with an error other than the reference being missing. This does
not verify whether the reference resolves to an actual object.
+get::
+ Reads the raw value of a single, exact reference. Instead of
+ recursively dereferencing symbolic references, this command prints the
+ direct target of the symref (e.g., ref: refs/heads/main). For regular
+ references, it prints the object ID (SHA-1) they point to.
+
OPTIONS
-------
diff --git a/builtin/refs.c b/builtin/refs.c
index 91548783b7..b473a78e18 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -2,6 +2,7 @@
#include "builtin.h"
#include "config.h"
#include "fsck.h"
+#include "hex.h"
#include "parse-options.h"
#include "refs.h"
#include "strbuf.h"
@@ -18,6 +19,9 @@
#define REFS_EXISTS_USAGE \
N_("git refs exists <ref>")
+#define REFS_GET_USAGE \
+ N_("git refs get <ref>")
+
static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
@@ -159,6 +163,43 @@ static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
return ret;
}
+static int cmd_refs_get(int argc, const char **argv, const char *prefix,
+ struct repository *repo UNUSED)
+{
+ const char *refname;
+ struct object_id oid;
+ unsigned int type;
+ int failure_errno = 0;
+ struct strbuf referent = STRBUF_INIT;
+
+ 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("refs get requires exactly one reference");
+
+ refname = *argv++;
+ if (refs_read_raw_ref(get_main_ref_store(the_repository), refname,
+ &oid, &referent, &type, &failure_errno)) {
+ die("'%s' - not a valid ref", refname);
+ }
+
+ if (type & REF_ISSYMREF) {
+ printf("ref: %s\n", referent.buf);
+ } else {
+ printf("%s\n", oid_to_hex(&oid));
+ }
+
+ strbuf_release(&referent);
+ return 0;
+}
+
int cmd_refs(int argc,
const char **argv,
const char *prefix,
@@ -169,6 +210,7 @@ int cmd_refs(int argc,
REFS_VERIFY_USAGE,
"git refs list " COMMON_USAGE_FOR_EACH_REF,
REFS_EXISTS_USAGE,
+ REFS_GET_USAGE,
NULL,
};
parse_opt_subcommand_fn *fn = NULL;
@@ -177,6 +219,7 @@ int cmd_refs(int argc,
OPT_SUBCOMMAND("verify", &fn, cmd_refs_verify),
OPT_SUBCOMMAND("list", &fn, cmd_refs_list),
OPT_SUBCOMMAND("exists", &fn, cmd_refs_exists),
+ OPT_SUBCOMMAND("get", &fn, cmd_refs_get),
OPT_END(),
};
diff --git a/t/meson.build b/t/meson.build
index 7974795fe4..0c8067c69d 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -213,6 +213,7 @@ integration_tests = [
't1460-refs-migrate.sh',
't1461-refs-list.sh',
't1462-refs-exists.sh',
+ 't1464-refs-get.sh',
't1500-rev-parse.sh',
't1501-work-tree.sh',
't1502-rev-parse-parseopt.sh',
diff --git a/t/t1464-refs-get.sh b/t/t1464-refs-get.sh
new file mode 100755
index 0000000000..166176c881
--- /dev/null
+++ b/t/t1464-refs-get.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+test_description='git refs get'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success 'setup repository' '
+ test_commit one &&
+ git tag -a -m "tagging one" my-tag one &&
+ git symbolic-ref refs/my-symref refs/heads/main &&
+ git symbolic-ref refs/dangling-symref refs/heads/no-such-branch
+'
+
+test_expect_success 'fails with no arguments' '
+ test_must_fail git refs get >out 2>err &&
+ test_grep "refs get requires exactly one reference" err
+'
+
+test_expect_success 'fails with too many arguments' '
+ test_must_fail git refs get HEAD HEAD >out 2>err &&
+ test_grep "refs get requires exactly one reference" err
+'
+
+test_expect_success 'get a branch head' '
+ git rev-parse main >expect &&
+ git refs get refs/heads/main >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get an annotated tag' '
+ git rev-parse my-tag >expect &&
+ git refs get refs/tags/my-tag >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get HEAD (a symbolic ref)' '
+ echo "ref: refs/heads/main" >expect &&
+ git refs get HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get a custom symbolic ref' '
+ echo "ref: refs/heads/main" >expect &&
+ git refs get refs/my-symref >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get a dangling symbolic ref' '
+ echo "ref: refs/heads/no-such-branch" >expect &&
+ git refs get refs/dangling-symref >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get a non-existent ref' '
+ test_must_fail git refs get refs/heads/no-such-branch 2>err &&
+ test_grep "not a valid ref" err
+'
+
+test_expect_success 'get does not perform DWIM' '
+ test_must_fail git refs get main 2>err &&
+ test_grep "not a valid ref" err
+'
+
+test_done
base-commit: ca2559c1d630eb4f04cdee2328aaf1c768907a9e
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-23 10:45 [GSoC][PATCH] builtin/refs: add 'get' subcommand Meet Soni
@ 2025-09-23 16:57 ` Ben Knoble
2025-09-24 6:32 ` Patrick Steinhardt
2025-09-23 21:50 ` Junio C Hamano
2025-09-24 6:32 ` Patrick Steinhardt
2 siblings, 1 reply; 11+ messages in thread
From: Ben Knoble @ 2025-09-23 16:57 UTC (permalink / raw)
To: Meet Soni; +Cc: git, ps, shejialuo
With apologies if I cover well-trodden ground, as I haven’t been closely following this effort.
> Le 23 sept. 2025 à 06:47, Meet Soni <meetsoni3017@gmail.com> a écrit :
>
> While `git-rev-parse(1)` and `git-show-ref(1)` can be used to read
> reference values, they have drawbacks for scripting and discoverability.
> `rev-parse` performs DWIM expansion which is unpredictable for scripts,
[snip]
> To address this, introduce a new plumbing command, `git refs get <ref>`.
> This new command provides three key advantages:
>
> - It requires an exact refname and does not perform expansion, making
> it safer and more predictable for scripting.
What are the disadvantages of rev-parse’s DWIMmery in scripts? I would think it makes handling user input easier (e.g., my custom script can take a local branch name without writing « refs/heads/ » on the command-line). OTOH, a script that wants to precisely identify a ref can do so already, no?
Since rev-parse presumably won’t go away, it might be ok to have 2 ways of parsing (one with magic and one without), but that might be back to the same boat of not having a unified interface 😅
Perhaps later we can add a « --dwim » flag for looser parsing, giving scripteds flexibility but strictness by default?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-23 10:45 [GSoC][PATCH] builtin/refs: add 'get' subcommand Meet Soni
2025-09-23 16:57 ` Ben Knoble
@ 2025-09-23 21:50 ` Junio C Hamano
2025-09-24 6:32 ` Patrick Steinhardt
2025-09-24 6:32 ` Patrick Steinhardt
2 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2025-09-23 21:50 UTC (permalink / raw)
To: Meet Soni; +Cc: git, ps, shejialuo
Meet Soni <meetsoni3017@gmail.com> writes:
> While `git-rev-parse(1)` and `git-show-ref(1)` can be used to read
> reference values, they have drawbacks for scripting and discoverability.
> `rev-parse` performs DWIM expansion which is unpredictable for scripts,
> and `show-ref --verify` is difficult to discover and cannot read the
> direct target of a symbolic reference.
Well "refs get" is even harder to discover (it is not even in Git
2.50's manual that is available everywhere on the net), so difficult
to discover is not a good excuse. In a sense show-ref was invented
exactly to serve as something like "refs get" you are writing, so I
wonder if a better approach is to extend it instead of introducing
a new subcommand in a distant place from it?
Perhaps "show-ref --verify --no-deref" or something that does not
dereference but works directly on a symbolic ref?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-23 16:57 ` Ben Knoble
@ 2025-09-24 6:32 ` Patrick Steinhardt
0 siblings, 0 replies; 11+ messages in thread
From: Patrick Steinhardt @ 2025-09-24 6:32 UTC (permalink / raw)
To: Ben Knoble; +Cc: Meet Soni, git, shejialuo
On Tue, Sep 23, 2025 at 12:57:04PM -0400, Ben Knoble wrote:
> With apologies if I cover well-trodden ground, as I haven’t been closely following this effort.
>
> > Le 23 sept. 2025 à 06:47, Meet Soni <meetsoni3017@gmail.com> a écrit :
> >
> > While `git-rev-parse(1)` and `git-show-ref(1)` can be used to read
> > reference values, they have drawbacks for scripting and discoverability.
> > `rev-parse` performs DWIM expansion which is unpredictable for scripts,
>
> [snip]
>
> > To address this, introduce a new plumbing command, `git refs get <ref>`.
> > This new command provides three key advantages:
> >
> > - It requires an exact refname and does not perform expansion, making
> > it safer and more predictable for scripting.
>
> What are the disadvantages of rev-parse’s DWIMmery in scripts? I would
> think it makes handling user input easier (e.g., my custom script can
> take a local branch name without writing « refs/heads/ » on the
> command-line). OTOH, a script that wants to precisely identify a ref
> can do so already, no?
>
> Since rev-parse presumably won’t go away, it might be ok to have 2
> ways of parsing (one with magic and one without), but that might be
> back to the same boat of not having a unified interface 😅
>
> Perhaps later we can add a « --dwim » flag for looser parsing, giving
> scripteds flexibility but strictness by default?
I think having such a "--dwim" flag at a later point could be a good
idea, yeah.
Patrick
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-23 21:50 ` Junio C Hamano
@ 2025-09-24 6:32 ` Patrick Steinhardt
2025-09-24 15:29 ` Ben Knoble
0 siblings, 1 reply; 11+ messages in thread
From: Patrick Steinhardt @ 2025-09-24 6:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Meet Soni, git, shejialuo
On Tue, Sep 23, 2025 at 02:50:46PM -0700, Junio C Hamano wrote:
> Meet Soni <meetsoni3017@gmail.com> writes:
>
> > While `git-rev-parse(1)` and `git-show-ref(1)` can be used to read
> > reference values, they have drawbacks for scripting and discoverability.
> > `rev-parse` performs DWIM expansion which is unpredictable for scripts,
> > and `show-ref --verify` is difficult to discover and cannot read the
> > direct target of a symbolic reference.
>
> Well "refs get" is even harder to discover (it is not even in Git
> 2.50's manual that is available everywhere on the net), so difficult
> to discover is not a good excuse. In a sense show-ref was invented
> exactly to serve as something like "refs get" you are writing, so I
> wonder if a better approach is to extend it instead of introducing
> a new subcommand in a distant place from it?
>
> Perhaps "show-ref --verify --no-deref" or something that does not
> dereference but works directly on a symbolic ref?
For now: yes, it's more difficult to discover for sure. But users will
adjust over time as they get more familiar with git-refs(1), and from
thereon I think it will become significantly easier to discover that
subcommand.
git-refs(1) already hosts everything needed to handle references, so
from my point of view it is only natural to also provide an easy way to
read a single reference to complete the picture.
Patrick
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-23 10:45 [GSoC][PATCH] builtin/refs: add 'get' subcommand Meet Soni
2025-09-23 16:57 ` Ben Knoble
2025-09-23 21:50 ` Junio C Hamano
@ 2025-09-24 6:32 ` Patrick Steinhardt
2 siblings, 0 replies; 11+ messages in thread
From: Patrick Steinhardt @ 2025-09-24 6:32 UTC (permalink / raw)
To: Meet Soni; +Cc: git, shejialuo
On Tue, Sep 23, 2025 at 04:15:33PM +0530, Meet Soni wrote:
> diff --git a/Documentation/git-refs.adoc b/Documentation/git-refs.adoc
> index bfa9b3ea2d..f07fe8c864 100644
> --- a/Documentation/git-refs.adoc
> +++ b/Documentation/git-refs.adoc
> @@ -19,6 +19,7 @@ git refs list [--count=<count>] [--shell|--perl|--python|--tcl]
> [(--exclude=<pattern>)...] [--start-after=<marker>]
> [ --stdin | (<pattern>...)]
> git refs exists <ref>
> +git refs get <ref>
>
> DESCRIPTION
> -----------
> @@ -45,6 +46,12 @@ exists::
> failed with an error other than the reference being missing. This does
> not verify whether the reference resolves to an actual object.
>
> +get::
> + Reads the raw value of a single, exact reference. Instead of
Let's say "fully qualified" instead of "exact".
> + recursively dereferencing symbolic references, this command prints the
> + direct target of the symref (e.g., ref: refs/heads/main). For regular
> + references, it prints the object ID (SHA-1) they point to.
I'd drop the reference to SHA1 here, as it may be any object hash.
> diff --git a/builtin/refs.c b/builtin/refs.c
> index 91548783b7..b473a78e18 100644
> --- a/builtin/refs.c
> +++ b/builtin/refs.c
> @@ -159,6 +163,43 @@ static int cmd_refs_exists(int argc, const char **argv, const char *prefix,
> return ret;
> }
>
> +static int cmd_refs_get(int argc, const char **argv, const char *prefix,
> + struct repository *repo UNUSED)
> +{
> + const char *refname;
> + struct object_id oid;
> + unsigned int type;
> + int failure_errno = 0;
> + struct strbuf referent = STRBUF_INIT;
Tiny nit: we typically order variables that aren't accessed by options
after the options array.
> + 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("refs get requires exactly one reference");
This should be translatable. Furthermore, we can probably use `usagef()`
instead to have a "usage:" prefix instead of "fatal:".
> + refname = *argv++;
> + if (refs_read_raw_ref(get_main_ref_store(the_repository), refname,
> + &oid, &referent, &type, &failure_errno)) {
> + die("'%s' - not a valid ref", refname);
We should discern by `failure_errno` here. Most importantly, I think we
should handle `ENOENT` and `EISDIR` specially to both mean that the
reference does not exist. So, e.g.:
if (refs_read_raw_ref(get_main_ref_store(the_repository), refname,
&oid, &referent, &type, &failure_errno)) {
if (failure_errno == ENOENT || failure_errno == EISDIR)
die(_("reference does not exist"));
else
die_errno(_("failed to look up reference"));
}
> + }
> +
> + if (type & REF_ISSYMREF) {
> + printf("ref: %s\n", referent.buf);
> + } else {
> + printf("%s\n", oid_to_hex(&oid));
> + }
We can drop the curly braces around single-line bodies.
Patrick
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-24 6:32 ` Patrick Steinhardt
@ 2025-09-24 15:29 ` Ben Knoble
2025-09-24 17:11 ` Junio C Hamano
0 siblings, 1 reply; 11+ messages in thread
From: Ben Knoble @ 2025-09-24 15:29 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Junio C Hamano, Meet Soni, git, shejialuo
> Le 24 sept. 2025 à 02:37, Patrick Steinhardt <ps@pks.im> a écrit :
>
> On Tue, Sep 23, 2025 at 02:50:46PM -0700, Junio C Hamano wrote:
>> Meet Soni <meetsoni3017@gmail.com> writes:
>>
>>> While `git-rev-parse(1)` and `git-show-ref(1)` can be used to read
>>> reference values, they have drawbacks for scripting and discoverability.
>>> `rev-parse` performs DWIM expansion which is unpredictable for scripts,
>>> and `show-ref --verify` is difficult to discover and cannot read the
>>> direct target of a symbolic reference.
>>
>> Well "refs get" is even harder to discover (it is not even in Git
>> 2.50's manual that is available everywhere on the net), so difficult
>> to discover is not a good excuse. In a sense show-ref was invented
>> exactly to serve as something like "refs get" you are writing, so I
>> wonder if a better approach is to extend it instead of introducing
>> a new subcommand in a distant place from it?
>>
>> Perhaps "show-ref --verify --no-deref" or something that does not
>> dereference but works directly on a symbolic ref?
>
> For now: yes, it's more difficult to discover for sure. But users will
> adjust over time as they get more familiar with git-refs(1), and from
> thereon I think it will become significantly easier to discover that
> subcommand.
I think this goes to perhaps some of my unasked questions: who is the target audience? My experience suggest that most mostly-porcelain users don’t acquire familiarity with scripting commands, so it sounds like we’re talking about script-writers here (and in the commit message).
But how do we encourage script writers to discover these things? 🤔 Hm.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-24 15:29 ` Ben Knoble
@ 2025-09-24 17:11 ` Junio C Hamano
2025-09-25 6:25 ` Patrick Steinhardt
0 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2025-09-24 17:11 UTC (permalink / raw)
To: Ben Knoble; +Cc: Patrick Steinhardt, Meet Soni, git, shejialuo
Ben Knoble <ben.knoble@gmail.com> writes:
>>> Perhaps "show-ref --verify --no-deref" or something that does not
>>> dereference but works directly on a symbolic ref?
>>
>> For now: yes, it's more difficult to discover for sure. But users will
>> adjust over time as they get more familiar with git-refs(1), and from
>> thereon I think it will become significantly easier to discover that
>> subcommand.
But unfortunately, that is a tautology, isn't it? With the same
effort to advertise git-refs to make it more familiar to the
"users", you can make "show-ref" familiar to the same "users", and
problem solved, without a need to do anything to "git-refs"?
> I think this goes to perhaps some of my unasked questions: who is
> the target audience? My experience suggest that most
> mostly-porcelain users don’t acquire familiarity with scripting
> commands, so it sounds like we’re talking about script-writers
> here (and in the commit message).
>
> But how do we encourage script writers to discover these things? 🤔 Hm.
Great question. I understand what the patch author is trying to
achieve (i.e. "consolidate ref-related functionality into git-refs",
which is the title of GSoC project [*]), but what are we, as Git
project, trying to achive by "consolidating"? I often cannot shake
the feeling that it may a make-work job without a clear answer to
that question. Or perhps xkcd.com/927/?
Perhaps the hope is to have a single kitchen sink "git refs" command
that does anything related to "refs", so that they only need to
learn this single command (and unlearn all the previous experiences
they gained) and after that, they do not have to "discover" more
things?
[Reference]
* https://summerofcode.withgoogle.com/programs/2025/projects/xVrT5e2q
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-24 17:11 ` Junio C Hamano
@ 2025-09-25 6:25 ` Patrick Steinhardt
2025-09-25 18:08 ` D. Ben Knoble
0 siblings, 1 reply; 11+ messages in thread
From: Patrick Steinhardt @ 2025-09-25 6:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Ben Knoble, Meet Soni, git, shejialuo
On Wed, Sep 24, 2025 at 10:11:08AM -0700, Junio C Hamano wrote:
> Ben Knoble <ben.knoble@gmail.com> writes:
>
> >>> Perhaps "show-ref --verify --no-deref" or something that does not
> >>> dereference but works directly on a symbolic ref?
> >>
> >> For now: yes, it's more difficult to discover for sure. But users will
> >> adjust over time as they get more familiar with git-refs(1), and from
> >> thereon I think it will become significantly easier to discover that
> >> subcommand.
>
> But unfortunately, that is a tautology, isn't it? With the same
> effort to advertise git-refs to make it more familiar to the
> "users", you can make "show-ref" familiar to the same "users", and
> problem solved, without a need to do anything to "git-refs"?
I don't quite think so. The problem is that we have so many different
tools that relate to refs, and you have to remember all of them:
- `git show-refs --verify` to read a single reference, unless it's a
symbolic reference.
- `git symbolic-ref` to read symbolic refs.
- `git show-refs --exists` to check a reference for existence.
- `git show-ref` and `git for-each-ref` to list references.
- `git pack-refs` to optimize references.
- `git update-refs` to update references`
I'd claim that this is quite hard to remember. So...
> > I think this goes to perhaps some of my unasked questions: who is
> > the target audience? My experience suggest that most
> > mostly-porcelain users don’t acquire familiarity with scripting
> > commands, so it sounds like we’re talking about script-writers
> > here (and in the commit message).
> >
> > But how do we encourage script writers to discover these things? 🤔 Hm.
>
> Great question. I understand what the patch author is trying to
> achieve (i.e. "consolidate ref-related functionality into git-refs",
> which is the title of GSoC project [*]), but what are we, as Git
> project, trying to achive by "consolidating"? I often cannot shake
> the feeling that it may a make-work job without a clear answer to
> that question. Or perhps xkcd.com/927/?
>
> Perhaps the hope is to have a single kitchen sink "git refs" command
> that does anything related to "refs", so that they only need to
> learn this single command (and unlearn all the previous experiences
> they gained) and after that, they do not have to "discover" more
> things?
... yes, this is exactly the goal of this exercise. You basically only
need to know about the entrypoint git-refs(1). Once you know about it,
you don't have to discover all the other commands, as it is now way
easier to discover what ref-related functionality you have available.
You can easily use tab completion (well, once it's wired up), type `git
refs -h` to learn about evertyhing refs, and we now have a single
manpage that will tell you everything about ref-related use commands.
You could partially address that problem by providing a gitrefs(5)
manpage that gives an overview. And maybe that's still something one
could do, also to paint a bit of a broader picture. But documentation is
only part of the solution -- with git-refs(1) we get some "natural"
discoverability.
That's also where the "git refs get" proposal comes from. Sure, you can
use `git show-refs --verify`, potentially with a `--no-dereference` flag
if you want to read normal refs. But I would claim that this is almost
impossible to discover without searching through our manpages.
Patrick
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-25 6:25 ` Patrick Steinhardt
@ 2025-09-25 18:08 ` D. Ben Knoble
2025-09-25 18:43 ` Junio C Hamano
0 siblings, 1 reply; 11+ messages in thread
From: D. Ben Knoble @ 2025-09-25 18:08 UTC (permalink / raw)
To: Patrick Steinhardt; +Cc: Junio C Hamano, Meet Soni, git, shejialuo
On Thu, Sep 25, 2025 at 2:25 AM Patrick Steinhardt <ps@pks.im> wrote:
>
> On Wed, Sep 24, 2025 at 10:11:08AM -0700, Junio C Hamano wrote:
> > Ben Knoble <ben.knoble@gmail.com> writes:
> >
> > >>> Perhaps "show-ref --verify --no-deref" or something that does not
> > >>> dereference but works directly on a symbolic ref?
> > >>
> > >> For now: yes, it's more difficult to discover for sure. But users will
> > >> adjust over time as they get more familiar with git-refs(1), and from
> > >> thereon I think it will become significantly easier to discover that
> > >> subcommand.
> >
> > But unfortunately, that is a tautology, isn't it? With the same
> > effort to advertise git-refs to make it more familiar to the
> > "users", you can make "show-ref" familiar to the same "users", and
> > problem solved, without a need to do anything to "git-refs"?
>
> I don't quite think so. The problem is that we have so many different
> tools that relate to refs, and you have to remember all of them:
>
> - `git show-refs --verify` to read a single reference, unless it's a
> symbolic reference.
>
> - `git symbolic-ref` to read symbolic refs.
>
> - `git show-refs --exists` to check a reference for existence.
>
> - `git show-ref` and `git for-each-ref` to list references.
>
> - `git pack-refs` to optimize references.
>
> - `git update-refs` to update references`
>
> I'd claim that this is quite hard to remember. So...
Agreed! To be clear: me asking questions should be taken as support
for this exercise :)
> > > I think this goes to perhaps some of my unasked questions: who is
> > > the target audience? My experience suggest that most
> > > mostly-porcelain users don’t acquire familiarity with scripting
> > > commands, so it sounds like we’re talking about script-writers
> > > here (and in the commit message).
> > >
> > > But how do we encourage script writers to discover these things? 🤔 Hm.
> >
> > Great question. I understand what the patch author is trying to
> > achieve (i.e. "consolidate ref-related functionality into git-refs",
> > which is the title of GSoC project [*]), but what are we, as Git
> > project, trying to achive by "consolidating"? I often cannot shake
> > the feeling that it may a make-work job without a clear answer to
> > that question. Or perhps xkcd.com/927/?
> >
> > Perhaps the hope is to have a single kitchen sink "git refs" command
> > that does anything related to "refs", so that they only need to
> > learn this single command (and unlearn all the previous experiences
> > they gained) and after that, they do not have to "discover" more
> > things?
>
> ... yes, this is exactly the goal of this exercise. You basically only
> need to know about the entrypoint git-refs(1). Once you know about it,
> you don't have to discover all the other commands, as it is now way
> easier to discover what ref-related functionality you have available.
> You can easily use tab completion (well, once it's wired up), type `git
> refs -h` to learn about evertyhing refs, and we now have a single
> manpage that will tell you everything about ref-related use commands.
Ah, but here's perhaps my question: tab-completion suggests primarily
porcelain users over plumbing users, to me ;)
I admit I blur the line quite a bit myself, being unafraid to string
together plumbing commands at a live shell (or make abominations like
git-greb [1]).
At any rate, the target audience need not be precise now. I hope my
confusion is clear, though :)
[1]: https://benknoble.github.io/blog/2025/09/17/blame/
> You could partially address that problem by providing a gitrefs(5)
> manpage that gives an overview. And maybe that's still something one
> could do, also to paint a bit of a broader picture. But documentation is
> only part of the solution -- with git-refs(1) we get some "natural"
> discoverability.
>
> That's also where the "git refs get" proposal comes from. Sure, you can
> use `git show-refs --verify`, potentially with a `--no-dereference` flag
> if you want to read normal refs. But I would claim that this is almost
> impossible to discover without searching through our manpages.
>
> Patrick
This all makes sense to me.
--
D. Ben Knoble
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GSoC][PATCH] builtin/refs: add 'get' subcommand
2025-09-25 18:08 ` D. Ben Knoble
@ 2025-09-25 18:43 ` Junio C Hamano
0 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2025-09-25 18:43 UTC (permalink / raw)
To: D. Ben Knoble; +Cc: Patrick Steinhardt, Meet Soni, git, shejialuo
"D. Ben Knoble" <ben.knoble@gmail.com> writes:
>> I don't quite think so. The problem is that we have so many different
>> tools that relate to refs, and you have to remember all of them:
Yup, but ...
>> - `git show-refs --verify` to read a single reference, unless it's a
>> symbolic reference.
>>
>> - `git symbolic-ref` to read symbolic refs.
>>
>> - `git show-refs --exists` to check a reference for existence.
>>
>> - `git show-ref` and `git for-each-ref` to list references.
>>
>> - `git pack-refs` to optimize references.
>>
>> - `git update-refs` to update references`
>>
>> I'd claim that this is quite hard to remember. So...
>
> Agreed! To be clear: me asking questions should be taken as support
> for this exercise :)
... the same thing can be said about subcommands of "git refs", all
of which you have to remember. I am not sure if this "everything
under "git refs" really makes much difference.
>> That's also where the "git refs get" proposal comes from. Sure, you can
>> use `git show-refs --verify`, potentially with a `--no-dereference` flag
>> if you want to read normal refs. But I would claim that this is almost
>> impossible to discover without searching through our manpages.
So? That still does not indicate adding yet another command to do
it is the right solution to the discover-ability problem. Instead
of shifting and moving things around, reimplementing things to risk
introducing new bugs, wouldn't it be more productive to spend effort
on improving the documentation and possibly filling the gaps of
features?
Thanks.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-09-25 18:43 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-23 10:45 [GSoC][PATCH] builtin/refs: add 'get' subcommand Meet Soni
2025-09-23 16:57 ` Ben Knoble
2025-09-24 6:32 ` Patrick Steinhardt
2025-09-23 21:50 ` Junio C Hamano
2025-09-24 6:32 ` Patrick Steinhardt
2025-09-24 15:29 ` Ben Knoble
2025-09-24 17:11 ` Junio C Hamano
2025-09-25 6:25 ` Patrick Steinhardt
2025-09-25 18:08 ` D. Ben Knoble
2025-09-25 18:43 ` Junio C Hamano
2025-09-24 6:32 ` Patrick Steinhardt
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).