Re: [PATCH v6 6/6] refs: add GIT_REFERENCE_BACKEND to specify reference backend
- From
Patrick Steinhardt <ps@pks.im>
- Date
- Feb 17, 2026, 07:24 UTC
- Message-ID
- <aZQXrRuX3nsnuyEw@pks.im>
- In-Reply-To
- <20260214-kn-alternate-ref-dir-v6-6-86a82c77cf59@gmail.com>
On Sat, Feb 14, 2026 at 11:34:19PM +0100, Karthik Nayak wrote:
Show 20 quoted lines
> Git allows setting a different object directory via > 'GIT_OBJECT_DIRECTORY', but provides no equivalent for references. In > the previous commit we extended the 'extensions.refStorage' config to > also support an URI input for reference backend with location. > > Let's also add a new environment variable 'GIT_REFERENCE_BACKEND' that > takes in the same input as the config variable. Having an environment > variable allows us to modify the reference backend and location on the > fly for individual Git commands. > > The environment variable also allows usage of alternate reference > directories during 'git-clone(1)' and 'git-init(1)'. Add the config to > the repository when created with the environment variable set. > > When initializing the repository with an alternate reference folder, > create the required stubs in the repositories $GIT_DIR. The inverse, > i.e. removal of the ref store doesn't clean up the stubs in the $GIT_DIR > since that would render it unusable. Removal of ref store is only used > when migrating between ref formats and cleanup of the $GIT_DIR doesn't > make sense in such a situation.
Nice.
Show 27 quoted lines
> diff --git a/refs.c b/refs.c
> index 87ef54abd4..6b3883a325 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -2192,16 +2192,21 @@ int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *e
> {
> int ret = refs->be->create_on_disk(refs, flags, err);
>
> - if (!ret &&
> - ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
> - struct strbuf msg = STRBUF_INIT;
> -
> - strbuf_addf(&msg, "this repository uses the %s format", refs->be->name);
> - refs_create_refdir_stubs(refs->repo, refs->gitdir, msg.buf);
> - strbuf_release(&msg);
> + if (!ret) {
> + /* Creation of stubs for linked worktrees are handled in the worktree code. */
> + if (!(flags & REF_STORE_CREATE_ON_DISK_IS_WORKTREE) && refs->repo->ref_storage_payload) {
> + refs_create_refdir_stubs(refs->repo, refs->repo->gitdir,
> + "repository uses alternate refs storage");
> + } else if (ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
> + struct strbuf msg = STRBUF_INIT;
> + strbuf_addf(&msg, "this repository uses the %s format", refs->be->name);
> + refs_create_refdir_stubs(refs->repo, refs->gitdir, msg.buf);
> + strbuf_release(&msg);
> + }
> }Okay, this here is the reason why you've moved the stub creation into the generic parts. Makes sense.
> > return ret; > + > }
There's a stray newline here.
Show 14 quoted lines
> diff --git a/setup.c b/setup.c > index d407f3347b..90cb9be578 100644 > --- a/setup.c > +++ b/setup.c > @@ -2337,7 +2357,8 @@ void initialize_repository_version(int hash_algo, > * the remote repository's format. > */ > if (hash_algo != GIT_HASH_SHA1_LEGACY || > - ref_storage_format != REF_STORAGE_FORMAT_FILES) > + ref_storage_format != REF_STORAGE_FORMAT_FILES || > + the_repository->ref_storage_payload) > target_version = GIT_REPO_VERSION_READ; > > if (hash_algo != GIT_HASH_SHA1_LEGACY && hash_algo != GIT_HASH_UNKNOWN)
Right. If we've got a payload during init we know that we must use the repository extension. Makes sense.
Show 23 quoted lines
> @@ -2346,11 +2367,20 @@ void initialize_repository_version(int hash_algo,
> else if (reinit)
> repo_config_set_gently(the_repository, "extensions.objectformat", NULL);
>
> - if (ref_storage_format != REF_STORAGE_FORMAT_FILES)
> + if (the_repository->ref_storage_payload) {
> + struct strbuf ref_uri = STRBUF_INIT;
> +
> + strbuf_addf(&ref_uri, "%s://%s",
> + ref_storage_format_to_name(ref_storage_format),
> + the_repository->ref_storage_payload);
> + repo_config_set(the_repository, "extensions.refstorage", ref_uri.buf);
> + strbuf_release(&ref_uri);
> + } else if (ref_storage_format != REF_STORAGE_FORMAT_FILES) {
> repo_config_set(the_repository, "extensions.refstorage",
> ref_storage_format_to_name(ref_storage_format));
> - else if (reinit)
> + } else if (reinit) {
> repo_config_set_gently(the_repository, "extensions.refstorage", NULL);
> + }
>
> if (reinit) {
> struct strbuf config = STRBUF_INIT;And here we write the payload into the configuration, if we've got one.
> diff --git a/t/t1423-ref-backend.sh b/t/t1423-ref-backend.sh > index 9912433b8c..b743c03a59 100755 > --- a/t/t1423-ref-backend.sh > +++ b/t/t1423-ref-backend.sh
[snip]
Show 21 quoted lines
> +test_expect_success 'initializing repository with alt ref directory' ' > + test_when_finished "rm -rf repo refdir" && > + mkdir refdir && > + BACKEND="$(test_detect_ref_format)://$(pwd)/refdir" && > + GIT_REFERENCE_BACKEND=$BACKEND git init repo && > + ( > + cd repo && > + > + git config get extensions.refstorage >expect && > + echo $BACKEND >actual && > + test_cmp expect actual && > + > + test_commit 1 && > + test_commit 2 && > + test_commit 3 && > + git refs list >out && > + test_grep "refs/tags/1" out && > + test_grep "refs/tags/2" out && > + test_grep "refs/tags/3" out > + ) > +'
Should we also verify that the refdir contains the data and that the repository only contains stubs?
Show 21 quoted lines
> +test_expect_success 'cloning repository with alt ref directory' ' > + test_when_finished "rm -rf source repo refdir" && > + mkdir refdir && > + > + git init source && > + test_commit -C source 1 && > + test_commit -C source 2 && > + test_commit -C source 3 && > + > + BACKEND="$(test_detect_ref_format)://$(pwd)/refdir" && > + GIT_REFERENCE_BACKEND=$BACKEND git clone source repo && > + > + git -C repo config get extensions.refstorage >expect && > + echo $BACKEND >actual && > + test_cmp expect actual && > + > + git -C source for-each-ref refs/tags/ >expect && > + git -C repo for-each-ref refs/tags/ >actual && > + test_cmp expect actual > +' > +
Same question here.
Thanks!
Patrick