From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: Eric Sunshine <sunshine@sunshineco.com>
Subject: [PATCH v2] symbolic-ref: teach "--[no-]recurse" option
Date: Fri, 07 Oct 2022 21:34:35 -0700 [thread overview]
Message-ID: <xmqqsfjzaq78.fsf@gitster.g> (raw)
In-Reply-To: <xmqqleprcn08.fsf@gitster.g> (Junio C. Hamano's message of "Fri, 07 Oct 2022 15:00:39 -0700")
Suppose you are managing many maintenance tracks in your project,
and some of the more recent ones are maint-2.36 and maint-2.37.
Further imagine that your project recently tagged the official 2.38
release, which means you would need to start maint-2.38 track soon,
by doing:
$ git checkout -b maint-2.38 v2.38.0^0
$ git branch --list 'maint-2.3[6-9]'
* maint-2.38
maint-2.36
maint-2.37
So far, so good. But it also is reasonable to want not to have to
worry about which maintenance track is the latest, by pointing a
more generic-sounding 'maint' branch at it, by doing:
$ git symbolic-ref refs/heads/maint refs/heads/maint-2.38
which would allow you to say "whichever it is, check out the latest
maintenance track", by doing:
$ git checkout maint
$ git branch --show-current
maint-2.38
It is arguably better to say that we are on 'maint-2.38' rather than
on 'maint', and "git merge/pull" would record "into maint-2.38" and
not "into maint", so I think what we have is a good behaviour.
One thing that is slightly irritating, however, is that I do not
think there is a good way (other than "cat .git/HEAD") to learn that
you checked out 'maint' to get into that state. Just like the output
of "git branch --show-current" shows above, "git symbolic-ref HEAD"
would report 'refs/heads/maint-2.38', bypassing the intermediate
symbolic ref at 'refs/heads/maint' that is pointed at by HEAD.
The internal resolve_ref() API already has the necessary support for
stopping after resolving a single level of a symbolic-ref, and we
can expose it by adding a "--[no-]recurse" option to the command.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* Updates documentation, which was entirely lacking in v1, with no
other changes.
Documentation/git-symbolic-ref.txt | 9 +++++++++
builtin/symbolic-ref.c | 16 ++++++++++------
t/t1401-symbolic-ref.sh | 14 ++++++++++++++
3 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
index ef68ad2b71..3b5a97ea2b 100644
--- a/Documentation/git-symbolic-ref.txt
+++ b/Documentation/git-symbolic-ref.txt
@@ -46,6 +46,15 @@ OPTIONS
When showing the value of <name> as a symbolic ref, try to shorten the
value, e.g. from `refs/heads/master` to `master`.
+--recurse::
+--no-recurse::
+ When showing the value of <name> as a symbolic ref, if
+ <name> refers to another symbolic ref, follow such a chain
+ of symbolic refs until the result no longer points at a
+ symbolic ref (`--recurse`, which is the default).
+ `--no-recurse` stops after dereferencing only a single level
+ of symbolic ref.
+
-m::
Update the reflog for <name> with <reason>. This is valid only
when creating or updating a symbolic ref.
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index e547a08d6c..1af27b3a68 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -10,10 +10,13 @@ static const char * const git_symbolic_ref_usage[] = {
NULL
};
-static int check_symref(const char *HEAD, int quiet, int shorten, int print)
+static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, int print)
{
- int flag;
- const char *refname = resolve_ref_unsafe(HEAD, 0, NULL, &flag);
+ int resolve_flags, flag;
+ const char *refname;
+
+ resolve_flags = (recurse ? 0 : RESOLVE_REF_NO_RECURSE);
+ refname = resolve_ref_unsafe(HEAD, resolve_flags, NULL, &flag);
if (!refname)
die("No such ref: %s", HEAD);
@@ -35,13 +38,14 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int print)
int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
{
- int quiet = 0, delete = 0, shorten = 0, ret = 0;
+ int quiet = 0, delete = 0, shorten = 0, recurse = 1, ret = 0;
const char *msg = NULL;
struct option options[] = {
OPT__QUIET(&quiet,
N_("suppress error message for non-symbolic (detached) refs")),
OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")),
OPT_BOOL(0, "short", &shorten, N_("shorten ref output")),
+ OPT_BOOL(0, "recurse", &recurse, N_("recursively dereference (default)")),
OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")),
OPT_END(),
};
@@ -55,7 +59,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
if (delete) {
if (argc != 1)
usage_with_options(git_symbolic_ref_usage, options);
- ret = check_symref(argv[0], 1, 0, 0);
+ ret = check_symref(argv[0], 1, 0, 0, 0);
if (ret)
die("Cannot delete %s, not a symbolic ref", argv[0]);
if (!strcmp(argv[0], "HEAD"))
@@ -65,7 +69,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
switch (argc) {
case 1:
- ret = check_symref(argv[0], quiet, shorten, 1);
+ ret = check_symref(argv[0], quiet, shorten, recurse, 1);
break;
case 2:
if (!strcmp(argv[0], "HEAD") &&
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
index 132a1b885a..773a6e8e01 100755
--- a/t/t1401-symbolic-ref.sh
+++ b/t/t1401-symbolic-ref.sh
@@ -163,4 +163,18 @@ test_expect_success 'symbolic-ref can resolve d/f name (ENOTDIR)' '
test_cmp expect actual
'
+test_expect_success 'symbolic-ref pointing at another' '
+ git update-ref refs/heads/maint-2.37 HEAD &&
+ git symbolic-ref refs/heads/maint refs/heads/maint-2.37 &&
+ git checkout maint &&
+
+ git symbolic-ref HEAD >actual &&
+ echo refs/heads/maint-2.37 >expect &&
+ test_cmp expect actual &&
+
+ git symbolic-ref --no-recurse HEAD >actual &&
+ echo refs/heads/maint >expect &&
+ test_cmp expect actual
+'
+
test_done
--
2.38.0-165-ga5df27c8e1
next prev parent reply other threads:[~2022-10-08 4:34 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-07 22:00 [PATCH] symbolic-ref: teach "--[no-]recurse" option Junio C Hamano
2022-10-08 3:35 ` Eric Sunshine
2022-10-08 4:20 ` Junio C Hamano
2022-10-08 4:34 ` Junio C Hamano [this message]
2022-10-08 4:54 ` [PATCH v2] " Eric Sunshine
2022-10-09 4:41 ` Junio C Hamano
2022-10-08 9:37 ` Bagas Sanjaya
2022-10-09 12:47 ` Junio C Hamano
2022-10-08 12:28 ` Philip Oakley
2022-10-08 15:28 ` Philip Oakley
2022-10-09 12:07 ` Junio C Hamano
2022-10-11 14:49 ` Philip Oakley
2022-10-09 22:13 ` [PATCH v3] " Junio C Hamano
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=xmqqsfjzaq78.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.