From: Jasper Mayone <me@jaspermayone.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, phillip.wood123@gmail.com,
sunshine@sunshineco.com, kristofferhaugsbakk@fastmail.com,
ben.knoble@gmail.com, haraldnordgren@gmail.com,
Jasper Mayone <me@jaspermayone.com>
Subject: [PATCH v5 4/5] ref-filter: add %(currentworktree)
Date: Wed, 11 Nov 2026 10:28:09 -0500 [thread overview]
Message-ID: <20261111152811.99986-5-me@jaspermayone.com> (raw)
In-Reply-To: <20261111152811.99986-1-me@jaspermayone.com>
%(worktreepath) names the worktree that has a branch checked out, or
is rebasing or bisecting it, but a format cannot tell if that worktree
is the current one. Comparing %(worktreepath) with a fixed path in
%(if:equals=...) does not work for every path, because a ")" ends the
atom.
Add %(currentworktree), which gives the path of the current worktree
when that worktree has the branch, and an empty string otherwise.
branch.c records these branches when it reads the worktrees, in a
second map next to the one that %(worktreepath) uses, so the lookup is
one map lookup per ref.
The next commit uses it in "git branch".
Suggested-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Jasper Mayone <me@jaspermayone.com>
---
Documentation/git-for-each-ref.adoc | 7 +++++++
branch.c | 25 ++++++++++++++++++-------
branch.h | 7 +++++++
ref-filter.c | 10 ++++++++++
t/t6302-for-each-ref-filter.sh | 21 +++++++++++++++++++++
5 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc
index 4456b4809a..5e2da92ee2 100644
--- a/Documentation/git-for-each-ref.adoc
+++ b/Documentation/git-for-each-ref.adoc
@@ -193,6 +193,13 @@ but if used together the last option is selected.
the `NUL` after the path and then for the `LF` that ends each
record.
+`currentworktree`::
+ The absolute path to the current worktree, if the ref is checked
+ out there, in the same sense as for `worktreepath`. Empty string
+ otherwise, also when the ref is checked out only in other
+ worktrees. Use it with `%(if)` to treat the current worktree
+ differently from the others.
+
`ahead-behind:<commit-ish>`::
Two integers, separated by a space, demonstrating the number of
commits ahead and behind, respectively, when comparing the output
diff --git a/branch.c b/branch.c
index 87f3ffc35f..4de789b7ae 100644
--- a/branch.c
+++ b/branch.c
@@ -386,6 +386,8 @@ static int initialized_checked_out_branches;
static struct strmap current_checked_out_branches = STRMAP_INIT;
/* Like current_checked_out_branches, without the "update-ref" branches. */
static struct strmap checked_out_worktrees = STRMAP_INIT;
+/* The subset of checked_out_worktrees that the current worktree has. */
+static struct strmap current_worktree_branches = STRMAP_INIT;
enum branch_checkout_kind {
BRANCH_CHECKOUT_KIND_CHECKOUT,
@@ -404,11 +406,11 @@ static struct checked_out_branch *checked_out_branches;
static size_t checked_out_branches_alloc, checked_out_branches_nr;
static void register_checked_out_branch(const char *prefix, const char *name,
- const char *path,
+ const struct worktree *wt,
enum branch_checkout_kind kind)
{
char *refname = xstrfmt("%s%s", prefix, name);
- char *path_copy = xstrdup(path);
+ char *path_copy = xstrdup(wt->path);
ALLOC_GROW(checked_out_branches, checked_out_branches_nr + 1,
checked_out_branches_alloc);
@@ -418,8 +420,11 @@ static void register_checked_out_branch(const char *prefix, const char *name,
checked_out_branches_nr++;
strmap_put(¤t_checked_out_branches, refname, path_copy);
- if (kind != BRANCH_CHECKOUT_KIND_UPDATE_REF)
+ if (kind != BRANCH_CHECKOUT_KIND_UPDATE_REF) {
strmap_put(&checked_out_worktrees, refname, path_copy);
+ if (wt->is_current)
+ strmap_put(¤t_worktree_branches, refname, path_copy);
+ }
}
static void prepare_checked_out_branches(void)
@@ -443,7 +448,7 @@ static void prepare_checked_out_branches(void)
continue;
if (wt->head_ref) {
- register_checked_out_branch("", wt->head_ref, wt->path,
+ register_checked_out_branch("", wt->head_ref, wt,
BRANCH_CHECKOUT_KIND_CHECKOUT);
}
@@ -451,7 +456,7 @@ static void prepare_checked_out_branches(void)
(state.rebase_in_progress || state.rebase_interactive_in_progress) &&
state.branch) {
register_checked_out_branch("refs/heads/", state.branch,
- wt->path,
+ wt,
BRANCH_CHECKOUT_KIND_REBASE);
}
wt_status_state_free_buffers(&state);
@@ -460,7 +465,7 @@ static void prepare_checked_out_branches(void)
state.bisecting_from) {
register_checked_out_branch("refs/heads/",
state.bisecting_from,
- wt->path,
+ wt,
BRANCH_CHECKOUT_KIND_BISECT);
}
wt_status_state_free_buffers(&state);
@@ -471,7 +476,7 @@ static void prepare_checked_out_branches(void)
struct string_list_item *item;
for_each_string_list_item(item, &update_refs) {
register_checked_out_branch("", item->string,
- wt->path,
+ wt,
BRANCH_CHECKOUT_KIND_UPDATE_REF);
}
string_list_clear(&update_refs, 1);
@@ -495,6 +500,12 @@ const char *branch_checked_out_worktree(const char *refname)
return strmap_get(&checked_out_worktrees, refname);
}
+const char *branch_checked_out_current_worktree(const char *refname)
+{
+ prepare_checked_out_branches();
+ return strmap_get(¤t_worktree_branches, refname);
+}
+
const char *branch_bisecting(const char *refname)
{
prepare_checked_out_branches();
diff --git a/branch.h b/branch.h
index 60cb92a3e4..744e1eec1d 100644
--- a/branch.h
+++ b/branch.h
@@ -115,6 +115,13 @@ const char *branch_checked_out(const char *refname);
*/
const char *branch_checked_out_worktree(const char *refname);
+/*
+ * Like branch_checked_out_worktree(), but only for the current
+ * worktree: return its path if it has the branch 'refname' checked
+ * out, or is rebasing or bisecting it. Otherwise return NULL.
+ */
+const char *branch_checked_out_current_worktree(const char *refname);
+
/*
* If the branch at 'refname' is currently used for bisecting in a
* worktree, then return the path to that worktree.
diff --git a/ref-filter.c b/ref-filter.c
index b636e56199..498d09da8f 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -142,6 +142,7 @@ enum atom_type {
ATOM_HEAD,
ATOM_COLOR,
ATOM_WORKTREEPATH,
+ ATOM_CURRENTWORKTREE,
ATOM_ALIGN,
ATOM_END,
ATOM_IF,
@@ -960,6 +961,7 @@ static struct {
[ATOM_HEAD] = { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
[ATOM_COLOR] = { "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
[ATOM_WORKTREEPATH] = { "worktreepath", SOURCE_NONE },
+ [ATOM_CURRENTWORKTREE] = { "currentworktree", SOURCE_NONE },
[ATOM_ALIGN] = { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
[ATOM_END] = { "end", SOURCE_NONE },
[ATOM_IF] = { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
@@ -2420,6 +2422,14 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
v->s = xstrdup("");
continue;
}
+ else if (atom_type == ATOM_CURRENTWORKTREE) {
+ const char *path = NULL;
+
+ if (ref->kind == FILTER_REFS_BRANCHES)
+ path = branch_checked_out_current_worktree(ref->refname);
+ v->s = xstrdup(path ? path : "");
+ continue;
+ }
else if (atom_type == ATOM_SYMREF)
refname = get_symref(atom, ref);
else if (atom_type == ATOM_UPSTREAM) {
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 317ed6f6cd..32522f1ff3 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -617,6 +617,27 @@ test_expect_success 'worktree atom ignores the HEAD of a bare repository' '
test_cmp expect actual
'
+test_expect_success 'currentworktree atom' '
+ test_when_finished "git -C current rebase --abort; rm -rf current; git worktree prune; git branch -D current" &&
+ git worktree add -b current current main &&
+ git -C current commit --allow-empty -m rebase-me &&
+ test_must_fail git -C current rebase -f -x false main &&
+ git for-each-ref --format="%(refname:short) [%(currentworktree)]" \
+ refs/heads/main refs/heads/current >actual &&
+ cat >expect <<-EOF &&
+ current []
+ main [$(pwd)]
+ EOF
+ test_cmp expect actual &&
+ git -C current for-each-ref --format="%(refname:short) [%(currentworktree)]" \
+ refs/heads/main refs/heads/current >actual &&
+ cat >expect <<-EOF &&
+ current [$(pwd)/current]
+ main []
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'start after with empty value' '
cat >expect <<-\EOF &&
refs/heads/main
--
2.56.0
next prev parent reply other threads:[~2026-11-11 15:28 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 17:33 [RFC PATCH 0/1] worktree list: add --merged and --no-merged Jasper Mayone
2026-10-21 17:33 ` [RFC PATCH 1/1] " Jasper Mayone
2026-10-23 18:30 ` Junio C Hamano
2026-10-24 6:25 ` Eric Sunshine
2026-10-24 16:53 ` [PATCH v2] worktree list: add --branch to select worktrees by branch Jasper Mayone
2026-10-25 14:47 ` Phillip Wood
2026-10-26 11:02 ` Phillip Wood
2026-10-28 6:02 ` Eric Sunshine
2026-10-28 15:27 ` Junio C Hamano
2026-10-28 11:32 ` Kristoffer Haugsbakk
2026-10-29 4:46 ` Jasper Mayone
2026-10-29 5:01 ` Eric Sunshine
2026-10-29 11:14 ` Phillip Wood
2026-10-29 14:23 ` Ben Knoble
2026-10-29 16:10 ` Phillip Wood
2026-10-30 14:21 ` [PATCH 0/2] worktree: treat a branch being rebased or bisected as checked out Jasper Mayone
2026-10-30 14:21 ` [PATCH 1/2] worktree remove: refuse a worktree in the middle of a rebase or bisect Jasper Mayone
2026-11-02 14:07 ` Phillip Wood
2026-11-02 17:57 ` Jasper Mayone
2026-10-30 14:21 ` [PATCH 2/2] ref-filter: name the worktree of a branch being rebased or bisected Jasper Mayone
2026-11-02 14:06 ` Phillip Wood
2026-11-02 17:57 ` Jasper Mayone
2026-10-30 22:55 ` [PATCH 0/2] worktree: treat a branch being rebased or bisected as checked out Junio C Hamano
2026-10-30 23:06 ` Jasper Mayone
2026-11-02 18:29 ` [PATCH v4 0/4] " Jasper Mayone
2026-11-02 18:29 ` [PATCH v4 1/4] worktree remove: refuse a worktree in the middle of an operation Jasper Mayone
2026-11-10 16:47 ` Phillip Wood
2026-11-10 17:09 ` Ben Knoble
2026-11-02 18:29 ` [PATCH v4 2/4] doc: for-each-ref: say how to read %(worktreepath) safely Jasper Mayone
2026-11-09 12:36 ` D. Ben Knoble
2026-11-09 15:10 ` Phillip Wood
2026-11-09 17:27 ` Ben Knoble
2026-11-09 20:17 ` Junio C Hamano
2026-11-10 16:47 ` Phillip Wood
2026-11-02 18:29 ` [PATCH v4 3/4] ref-filter: name the worktree of a branch being rebased or bisected Jasper Mayone
2026-11-10 16:47 ` Phillip Wood
2026-11-02 18:29 ` [PATCH v4 4/4] branch: do not mark the branch the current worktree is rebasing Jasper Mayone
2026-11-10 16:45 ` Phillip Wood
2026-11-10 16:49 ` [PATCH v4 0/4] worktree: treat a branch being rebased or bisected as checked out Phillip Wood
2026-11-11 15:28 ` [PATCH v5 0/5] " Jasper Mayone
2026-11-11 15:28 ` [PATCH v5 1/5] worktree remove: refuse a worktree in the middle of an operation Jasper Mayone
2026-11-11 15:28 ` [PATCH v5 2/5] doc: for-each-ref: say how to read %(worktreepath) safely Jasper Mayone
2026-11-11 15:28 ` [PATCH v5 3/5] ref-filter: name the worktree of a branch being rebased or bisected Jasper Mayone
2026-11-11 15:28 ` Jasper Mayone [this message]
2026-11-11 15:28 ` [PATCH v5 5/5] branch: do not mark the branch the current worktree is rebasing Jasper Mayone
2026-11-11 15:42 ` [PATCH v5 0/5] worktree: treat a branch being rebased or bisected as checked out Ben Knoble
2026-10-21 21:36 ` [RFC PATCH 0/1] worktree list: add --merged and --no-merged Harald Nordgren
2026-10-21 22:12 ` Junio C Hamano
2026-10-22 7:21 ` Harald Nordgren
2026-10-22 17:58 ` Kristoffer Haugsbakk
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=20261111152811.99986-5-me@jaspermayone.com \
--to=me@jaspermayone.com \
--cc=ben.knoble@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=haraldnordgren@gmail.com \
--cc=kristofferhaugsbakk@fastmail.com \
--cc=phillip.wood123@gmail.com \
--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.