Git development
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Patrick Steinhardt <ps@pks.im>
Cc: git@vger.kernel.org, Karthik Nayak <karthik.188@gmail.com>
Subject: Re: [PATCH v2 7/8] refs: fix recursing `get_main_ref_store()` with "onbranch" config
Date: Thu, 18 Jun 2026 12:40:35 -0400	[thread overview]
Message-ID: <20260618164035.GA1218204@coredump.intra.peff.net> (raw)
In-Reply-To: <20260615-b4-pks-refs-avoid-chdir-notify-reparent-v2-7-f4854aa99859@pks.im>

On Mon, Jun 15, 2026 at 03:56:53PM +0200, Patrick Steinhardt wrote:

> When we have an "onbranch" condition we need to ask the reference
> database whether HEAD currently points at the configured branch. This
> unfortunately creates a chicken-and-egg problem:
> 
>   - The reference database needs to read the configuration so that it
>     can configure itself.
> 
>   - The configuration needs to construct a reference database to fully
>     parse all of its conditionals.
> 
> The way we handle this is by simply excluding "onbranch" conditionals
> when we haven't yet configured the reference database.

My gut feeling upon reading this is that some part of the config reading
is being done wrong to create this chicken-and-egg situation.

I'd expect the ref database config (like the ref format) to be read not
through the regular config subsystem, but via read_repository_format()
and friends. And while that does build on the regular config code, it
should never enable includes at all. So includeIf.onbranch:foo.path is
just another uninteresting config key to it.

In other words, there should be two passes over the config file: one to
load basic repository information (and not respect includes), and one to
actually load what we think of as user-visible config[1].

And it seems to work. If I do this:

diff --git a/config.c b/config.c
index 45144f73c5..343af2cf9a 100644
--- a/config.c
+++ b/config.c
@@ -303,7 +303,7 @@ static int include_by_branch(struct config_include_data *data,
 	const char *refname, *shortname;
 
 	if (!data->repo || data->repo->ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
-		return 0;
+		BUG("chicken and egg");
 
 	refname = refs_resolve_ref_unsafe(get_main_ref_store(data->repo),
 					  "HEAD", 0, NULL, &flags);

and then:

  git config includeIf.onbranch:main.path alt-config
  git config -f .git/alt-config foo.bar baz
  git config foo.bar

then we correctly read the value without triggering this code path.

Looking back at the last commit that touched include_by_branch(), the
problem does not appear to be about a chicken-and-egg at all, though. It
is about reading config with includes when there is _no_ repository at
all. I.e., this:

  git config -f main-config includeIf.onbranch:main.path alt-config
  git config -f  alt-config foo.bar baz
  GIT_DIR=/does/not/exist git.compile config --include -f main-config foo.bar

will trigger that BUG() marker, and quietly returning "no match" (like
the current code does) is the right thing.

Looking below...

> The consequence is that we have recursion:
> 
>   1. We call `get_main_ref_store()`.
> 
>   2. We don't yet have a reference store, so we call `ref_store_init()`.
> 
>   3. We parse the configuration required for the reference store.
> 
>   4. We eventually end up in `include_by_branch()`.
> 
>   5. We have already configured the reference storage format, so we end
>      up calling `get_main_ref_store()` again.

Ah, the culprit seems to be ref_store_init() calling into the regular
config parser via repo_settings_get_log_all_ref_updates(). But that
feels weird to me. Either:

  1. It is application config that should not be something we need to
     load in order to initialize the backend. We could lazy-load it
     later, or rely on higher level code to set the option.

  2. It is crucial to the ref backend functioning, in which case we
     ought to be reading it alongside core.repositoryFormatVersion, etc.

-Peff

  parent reply	other threads:[~2026-06-18 16:40 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-10 14:57 [PATCH 0/9] refs: stop using `chdir_notify_reparent()` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 1/9] setup: inline `check_and_apply_repository_format()` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 2/9] setup: stop applying repository format twice Patrick Steinhardt
2026-06-12  9:00   ` Karthik Nayak
2026-06-15 12:36     ` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 3/9] setup: don't apply "GIT_REFERENCE_BACKEND" without a repository Patrick Steinhardt
2026-06-10 17:32   ` Junio C Hamano
2026-06-12  6:18     ` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 4/9] refs: unregister reference stores from "chdir_notify" Patrick Steinhardt
2026-06-12  9:18   ` Karthik Nayak
2026-06-15 12:36     ` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 5/9] chdir-notify: drop unused `chdir_notify_reparent()` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 6/9] repository: free main reference database Patrick Steinhardt
2026-06-12  9:20   ` Karthik Nayak
2026-06-10 14:57 ` [PATCH 7/9] refs: fix recursing `get_main_ref_store()` with "onbranch" config Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 8/9] refs: drop local buffer in `refs_compute_filesystem_location()` Patrick Steinhardt
2026-06-10 14:57 ` [PATCH 9/9] refs: always use absolute paths for reference stores Patrick Steinhardt
2026-06-12  9:58   ` Karthik Nayak
2026-06-15 12:36     ` Patrick Steinhardt
2026-06-11  6:53 ` [PATCH 0/9] refs: stop using `chdir_notify_reparent()` Jeff King
2026-06-12  6:18   ` Patrick Steinhardt
2026-06-13 14:00     ` Jeff King
2026-06-15 12:36       ` Patrick Steinhardt
2026-06-15 13:56 ` [PATCH v2 0/8] " Patrick Steinhardt
2026-06-15 13:56   ` [PATCH v2 1/8] setup: inline `check_and_apply_repository_format()` Patrick Steinhardt
2026-06-15 13:56   ` [PATCH v2 2/8] setup: stop applying repository format twice Patrick Steinhardt
2026-06-17 17:22     ` Justin Tobler
2026-06-15 13:56   ` [PATCH v2 3/8] setup: don't apply "GIT_REFERENCE_BACKEND" without a repository Patrick Steinhardt
2026-06-17 17:43     ` Justin Tobler
2026-06-18  6:53       ` Patrick Steinhardt
2026-06-15 13:56   ` [PATCH v2 4/8] refs: unregister reference stores from "chdir_notify" Patrick Steinhardt
2026-06-17 18:02     ` Justin Tobler
2026-06-17 18:07       ` Justin Tobler
2026-06-18  6:54       ` Patrick Steinhardt
2026-06-15 13:56   ` [PATCH v2 5/8] chdir-notify: drop unused `chdir_notify_reparent()` Patrick Steinhardt
2026-06-15 13:56   ` [PATCH v2 6/8] repository: free main reference database Patrick Steinhardt
2026-06-17 18:09     ` Justin Tobler
2026-06-15 13:56   ` [PATCH v2 7/8] refs: fix recursing `get_main_ref_store()` with "onbranch" config Patrick Steinhardt
2026-06-17 18:41     ` Justin Tobler
2026-06-18  5:59       ` Patrick Steinhardt
2026-06-18 14:15         ` Justin Tobler
2026-06-18 14:51           ` Patrick Steinhardt
2026-06-18 15:53             ` Justin Tobler
2026-06-18 16:40     ` Jeff King [this message]
2026-06-15 13:56   ` [PATCH v2 8/8] refs: drop local buffer in `refs_compute_filesystem_location()` Patrick Steinhardt
2026-06-18  6:54 ` [PATCH v3 0/8] refs: stop using `chdir_notify_reparent()` Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 1/8] setup: inline `check_and_apply_repository_format()` Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 2/8] setup: stop applying repository format twice Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 3/8] setup: don't apply "GIT_REFERENCE_BACKEND" without a repository Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 4/8] refs: unregister reference stores from "chdir_notify" Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 5/8] chdir-notify: drop unused `chdir_notify_reparent()` Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 6/8] repository: free main reference database Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 7/8] refs: fix recursing `get_main_ref_store()` with "onbranch" config Patrick Steinhardt
2026-06-18  6:54   ` [PATCH v3 8/8] refs: drop local buffer in `refs_compute_filesystem_location()` Patrick Steinhardt

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=20260618164035.GA1218204@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=karthik.188@gmail.com \
    --cc=ps@pks.im \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox