Subject: Re: [PATCH v5 3/4] refs: allow reference location in refstorage config

From: Patrick Steinhardt <[email-masked]>
Date: Mon, 9 Feb 2026 17:34:27 +0100

On Mon, Feb 09, 2026 at 04:58:20PM +0100, Karthik Nayak wrote:
> The 'extensions.refStorage' config is used to specify the reference
> backend for a given repository. Both the 'files' and 'reftable' backends
> utilize the $GIT_DIR as the reference folder by default in
> `get_main_ref_store()`.
> 
> Since the reference backends are pluggable, this means that they could
> work with out-of-tree reference directories too. Extend the 'refStorage'
> config to also support taking an URI input, where users can specify the
> reference backend and the location.
> 
> Add the required changes to obtain and propagate this value to the
> individual backends also add the necessary documentation and tests.

This reads as if this should have been two sentences.

> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index fbdaf2eb2e..94480be5c4 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -425,6 +425,39 @@ static int make_worktree_orphan(const char * ref, const struct add_opts *opts,
>  	return run_command(&cp);
>  }
>  
> +/*
> + * References for worktress are generally stored in '$GIT_DIR/worktrees/<wt_id>'.

s/worktress/worktrees/

> diff --git a/t/t1423-ref-backend.sh b/t/t1423-ref-backend.sh
> new file mode 100755
> index 0000000000..9c777b79f3
> --- /dev/null
> +++ b/t/t1423-ref-backend.sh
> @@ -0,0 +1,159 @@
> +#!/bin/sh
> +
> +test_description='Test reference backend URIs'
> +
> +. ./test-lib.sh
> +
> +# Run a git command with the provided reference storage. Reset the backend
> +# post running the command.
> +# Usage: run_with_uri <repo> <backend> <uri> <cmd>
> +#   <repo> is the relative path to the repo to run the command in.
> +#   <backend> is the original ref storage of the repo.
> +#   <uri> is the new URI to be set for the ref storage.
> +#   <cmd> is the git subcommand to be run in the repository.
> +run_with_uri() {
> +	repo=$1 &&
> +	backend=$2 &&
> +	uri=$3 &&
> +	cmd=$4 &&
> +
> +	git -C "$repo" config set core.repositoryformatversion 1
> +	git -C "$repo" config set extensions.refStorage "$uri" &&
> +	git -C "$repo" $cmd &&
> +	git -C "$repo" config set extensions.refStorage "$backend"
> +}
> +
> +# Test a repository with a given reference storage by running and comparing
> +# 'git refs list' before and after setting the new reference backend. If
> +# err_msg is set, expect the command to fail and grep for the provided err_msg.
> +# Usage: run_with_uri <repo> <backend> <uri> <cmd>
> +#   <repo> is the relative path to the repo to run the command in.
> +#   <backend> is the original ref storage of the repo.
> +#   <uri> is the new URI to be set for the ref storage.
> +#   <err_msg> (optional) if set, check if 'git-refs(1)' failed with the provided msg.
> +test_refs_backend() {
> +	repo=$1 &&
> +	backend=$2 &&
> +	uri=$3 &&
> +	err_msg=$4 &&
> +
> +	git -C "$repo" config set core.repositoryformatversion 1 &&
> +	if test -n "$err_msg";
> +	then
> +		git -C "$repo" config set extensions.refStorage "$uri" &&
> +		test_must_fail git -C "$repo" refs list 2>err &&
> +		test_grep "$err_msg" err
> +	else
> +		git -C "$repo" refs list >expect &&
> +		run_with_uri "$repo" "$backend" "$uri" "refs list" >actual &&
> +		test_cmp expect actual
> +	fi
> +}
> +
> +test_expect_success 'URI is invalid' '
> +	test_when_finished "rm -rf repo" &&
> +	git init repo &&
> +	test_refs_backend repo files "reftable@/home/reftable" \
> +		"invalid value for ${SQ}extensions.refstorage${SQ}"
> +'
> +
> +test_expect_success 'URI ends with colon' '
> +	test_when_finished "rm -rf repo" &&
> +	git init repo &&
> +	test_refs_backend repo files "reftable:" \
> +		"invalid value for ${SQ}extensions.refstorage${SQ}"
> +'
> +
> +test_expect_success 'unknown reference backend' '
> +	test_when_finished "rm -rf repo" &&
> +	git init repo &&
> +	test_refs_backend repo files "db://.git" \
> +		"invalid value for ${SQ}extensions.refstorage${SQ}"
> +'
> +
> +ref_formats="files reftable"
> +for from_format in $ref_formats
> +do
> +
> +for to_format in $ref_formats
> +do
> +	if test "$from_format" = "$to_format"
> +	then
> +		continue
> +	fi
> +
> +
> +	for dir in "$(pwd)/repo/.git" "./"

As "./" is a relative directory I expect it to be resolved relative to
"$GIT_DIR", right? Also, I don't see any tests that create the ref
directory outside of the repository. Should we maybe add one?

> +	do
> +
> +		test_expect_success "$read from $to_format backend, $dir dir" '
> +			test_when_finished "rm -rf repo" &&
> +			git init --ref-format=$from_format repo &&
> +			(
> +				cd repo &&
> +				test_commit 1 &&
> +				test_commit 2 &&
> +				test_commit 3 &&
> +
> +				git refs migrate --dry-run --ref-format=$to_format >out &&

Okay, we do the migration, but with "--dry-run". This should result in a
temporary staging directory, which is in fact somewhat interesting given
that "to_format" can now contain a payload. I assume it wouldn't have an
impact if such a payload was set here?

> +				BACKEND_PATH="$dir/$(sed "s/.* ${SQ}.git\/\(.*\)${SQ}/\1/" out)" &&

Hm. I have no idea what this is doing :)

> +				test_refs_backend . $from_format "$to_format://$BACKEND_PATH" "$method"
> +			)
> +		'

In general I think it would be sensible to also have a couple tests here
that exercise specific formats directly. Like:

  - Are the files created in the right spots for the files and reftable
    backend with a specific backend?

  - Does `git refs migrate` know to write the files into the correct
    location in case "--dry-run" wasn't passed?

  - Does git-init(1) and git-clone(1) initialize the refstore in a
    different location as expected?

  - Does creating a worktree work?

Patrick