{"thread":{"id":"64562","subject":"[PATCH v3 1/2] refs: support obtaining ref_store for given dir","startedAt":"2025-12-01T11:25:02Z","lastAt":"2026-01-22T12:36:07Z","messageCount":7,"participants":["Karthik Nayak","Patrick Steinhardt","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":2},"messages":[{"id":"531499","messageId":"20251201-kn-alternate-ref-dir-v3-1-c11b946bc2fa@gmail.com","threadId":"64562","inReplyTo":"20251201-kn-alternate-ref-dir-v3-0-c11b946bc2fa@gmail.com","subject":"[PATCH v3 1/2] refs: support obtaining ref_store for given dir","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-12-01T11:24:58Z","receivedAt":"2025-12-01T11:25:02Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The refs subsystem uses the `get_main_ref_store()` to obtain the main\nref_store for a given repository. In the upcoming patches we also want\nto create a ref_store for any given reference directory, which may exist\nin arbitrary paths. For the files backend and the reftable backend, the\nreference directory is generally the $GIT_DIR.\n\nTo support such behavior, extract out the core logic for creating out\nthe ref_store from `get_main_ref_store()` into a new function\n`get_ref_store_for_dir()` which can provide the ref_store for a\ngiven (repository, directory, reference format) combination.\n\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n refs.c | 13 ++++++++++---\n 1 file changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 965381367e..23f46867f2 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2177,6 +2177,15 @@ void ref_store_release(struct ref_store *ref_store)\n \tfree(ref_store->gitdir);\n }\n \n+static struct ref_store *get_ref_store_for_dir(struct repository *r,\n+\t\t\t\t\t       char *dir,\n+\t\t\t\t\t       enum ref_storage_format format)\n+{\n+\tstruct ref_store *ref_store = ref_store_init(r, format, dir,\n+\t\t\t\t\t\t     REF_STORE_ALL_CAPS);\n+\treturn maybe_debug_wrap_ref_store(dir, ref_store);\n+}\n+\n struct ref_store *get_main_ref_store(struct repository *r)\n {\n \tif (r->refs_private)\n@@ -2185,9 +2194,7 @@ struct ref_store *get_main_ref_store(struct repository *r)\n \tif (!r->gitdir)\n \t\tBUG(\"attempting to get main_ref_store outside of repository\");\n \n-\tr->refs_private = ref_store_init(r, r->ref_storage_format,\n-\t\t\t\t\t r->gitdir, REF_STORE_ALL_CAPS);\n-\tr->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);\n+\tr->refs_private = get_ref_store_for_dir(r, r->gitdir, r->ref_storage_format);\n \treturn r->refs_private;\n }\n \n\n-- \n2.51.2\n\n"},{"id":"531500","messageId":"20251201-kn-alternate-ref-dir-v3-0-c11b946bc2fa@gmail.com","threadId":"64562","inReplyTo":"20251119-kn-alternate-ref-dir-v1-0-4cf4a94c8bed@gmail.com","subject":"[PATCH v3 0/2] refs: allow setting the reference directory","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-12-01T11:24:57Z","receivedAt":"2025-12-01T11:25:02Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"While Git allows users to select different reference backends, unlike\nwith objects, there is no flexibility in selecting the reference\ndirectory. Currently, the reference format is obtained from the config\nof the repository and the reference directory is set to the $GIT_DIR.\n\nThis patch series adds a new ENV variable 'GIT_REF_URI' which takes the\nreference backend and path in a URI form:\n\n    <reference_backend>://<URI-for-resource>\n\nFor e.g. 'reftable:///foo' or 'files://$GIT_DIR/ref_migration.0xBsa0'.\n\nOne use case for this is migration between different backends. On the\nserver side, migrating from the files backend to the newly introduced\nreftable backend can be achieved by running 'git refs migrate'. However,\nfor large repositories with millions of references, this migration can\ntake from seconds to minutes.\n\nFor some background, at GitLab, the criteria for our migration was to\nreduce the downtime of the migrate ideally to zero. So running 'git refs\nmigrate --ref-format=reftable' by itself wouldn't work, since it scales\nwith the number of references and we have repos with millions of\nreferences, so we need to migrate without loosing any information. We\ncame up with the following plan:\n\n  1. Run git-pack-refs(1) and note timestamp of the generated packed-refs\n     file.\n  2. Run git refs migrate –dry-run.\n  3. If there are no ongoing reference requests (read/write)\n     a. Lock the repository by blocking incoming requests (done on a\n        layer above git, in Gitaly [1]).\n     b. If the timestamp of the packed-refs file has changed, unlock\n        the repo and repeat from step 1.\n     c. Apply all the loose refs to the dry-run reftable folder (this\n        requires support in Git to write refs to arbitrary folder).\n     d. Move the reftable dry-run folder into the GIT_DIR.\n     e. Swap the repo config\n     f. Unlock repo access\n\nUsing such a route, scales much better since we only have to worry about\nblocking the repository by O(ref written between #1 and #3a) and not\nO(refs in repo). But for doing so, we need to be able to write to a\narbitrary reference backend + path. This is to add the missing\nreferences to the dry-run reftable folder. This series, achieves that.\n\nThe first commit adds the required changes to create a 'ref_store' for a\ngiven path. The second commit parses the URI if available when creating\nthe main ref store.\n\nThis is based on top of 9a2fb147f2 (Git 2.52, 2025-11-17).\n\n[1]: https://gitlab.com/gitlab-org/gitaly\n\n---\nChanges in v3:\n- Cleanup some stale code which wasn't removed.\n- Localize strings which will be output to the user.\n- Remove additional defensive checks which are not needed.\n- Link to v2: https://patch.msgid.link/20251126-kn-alternate-ref-dir-v2-0-8b9f6f18f635@gmail.com\n\nChanges in v2:\n- Added more clarification and proper intent in the cover message.\n- Changed the format from '<ref_backend>://<path>' to\n  `<ref_backend>://<URI-for-resource>` as it much clearer.\n- Added logic to check for the '//' in the provided URI and a test for\n  the same.\n- In the tests:\n  - Use test_must_fail() instead of ! git\n  - Fix looped tests not using the variables correctly and ensure that\n    the test description is correct.\n- Link to v1: https://patch.msgid.link/20251119-kn-alternate-ref-dir-v1-0-4cf4a94c8bed@gmail.com\n\n---\n Documentation/git.adoc |   8 ++++\n environment.h          |   1 +\n refs.c                 |  68 +++++++++++++++++++++++++--\n t/meson.build          |   1 +\n t/t1423-ref-backend.sh | 121 +++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 196 insertions(+), 3 deletions(-)\n\nKarthik Nayak (2):\n      refs: support obtaining ref_store for given dir\n      refs: add GIT_REF_URI to specify reference backend and directory\n\nRange-diff versus v2:\n\n1:  5d37b2f0be = 1:  2b65f93e56 refs: support obtaining ref_store for given dir\n2:  493c7ca098 ! 2:  d5dbb2f112 refs: add GIT_REF_URI to specify reference backend and directory\n    @@ refs.c: static struct ref_store *get_ref_store_for_dir(struct repository *r,\n     +\tchar *format_string;\n     +\tchar *dir;\n     +\n    -+\tif (!uri || !uri[0]) {\n    -+\t\terror(\"reference backend uri is empty\");\n    ++\tif (!uri) {\n    ++\t\terror(_(\"reference backend uri is not provided\"));\n     +\t\tgoto cleanup;\n     +\t}\n     +\n     +\tif (string_list_split(&ref_backend_info, uri, \":\", 2) != 2) {\n    -+\t\terror(\"invalid reference backend uri format '%s'\", uri);\n    ++\t\terror(_(\"invalid reference backend uri format '%s'\"), uri);\n     +\t\tgoto cleanup;\n     +\t}\n     +\n     +\tformat_string = ref_backend_info.items[0].string;\n     +\tif (!starts_with(ref_backend_info.items[1].string, \"//\")) {\n    -+\t\terror(\"invalid reference backend uri format '%s'\", uri);\n    ++\t\terror(_(\"invalid reference backend uri format '%s'\"), uri);\n     +\t\tgoto cleanup;\n     +\t}\n     +\tdir = ref_backend_info.items[1].string + 2;\n     +\n    -+\tformat_string = ref_backend_info.items[0].string;\n    -+\tdir = ref_backend_info.items[1].string + 2;\n    -+\n    -+\tif (!dir || !dir[0]) {\n    -+\t\terror(\"invalid path in uri '%s'\", uri);\n    ++\tif (!dir[0]) {\n    ++\t\terror(_(\"invalid path in uri '%s'\"), uri);\n     +\t\tgoto cleanup;\n     +\t}\n     +\n     +\tformat = ref_storage_format_by_name(format_string);\n     +\tif (format == REF_STORAGE_FORMAT_UNKNOWN) {\n    -+\t\terror(\"unknown reference backend '%s'\", format_string);\n    ++\t\terror(_(\"unknown reference backend '%s'\"), format_string);\n     +\t\tgoto cleanup;\n     +\t}\n     +\n    @@ t/t1423-ref-backend.sh (new)\n     +\t\tGIT_REF_URI=\"\" &&\n     +\t\texport GIT_REF_URI &&\n     +\t\ttest_must_fail git refs list 2>err &&\n    -+\t\ttest_grep \"reference backend uri is empty\" err\n    ++\t\ttest_grep \"invalid reference backend uri format\" err\n     +\t)\n     +'\n     +\n\n\nbase-commit: 9a2fb147f2c61d0cab52c883e7e26f5b7948e3ed\nchange-id: 20251105-kn-alternate-ref-dir-3e572e8cd0ef\n\nThanks\n- Karthik\n\n"},{"id":"531501","messageId":"20251201-kn-alternate-ref-dir-v3-2-c11b946bc2fa@gmail.com","threadId":"64562","inReplyTo":"20251201-kn-alternate-ref-dir-v3-0-c11b946bc2fa@gmail.com","subject":"[PATCH v3 2/2] refs: add GIT_REF_URI to specify reference backend and directory","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-12-01T11:24:59Z","receivedAt":"2025-12-01T11:25:03Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Git allows setting a different object directory via\n'GIT_OBJECT_DIRECTORY', but provides no equivalent for references.\nThis asymmetry makes it difficult to test different reference backends\nor use alternative reference storage locations without modifying the\nrepository structure.\n\nAdd a new environment variable 'GIT_REF_URI' that specifies both the\nreference backend and directory path using a URI format:\n\n    <ref_backend>://<URI-for-resource>\n\nWhen set, this variable is used to obtain the main reference store for\nall Git commands. The variable is checked in `get_main_ref_store()`\nwhen lazily assigning `repo->refs_private`. We cannot initialize this\nearlier in `repo_set_gitdir()` because the repository's hash algorithm\nisn't known at that point, and the reftable backend requires this\ninformation during initialization.\n\nWhen used with worktrees, the specified directory is treated as the\nreference directory for all worktree operations.\n\nAdd a new test file 't1423-ref-backend.sh' to test this environment\nvariable.\n\nHelped-by: Jean-Noël Avila <jn.avila@free.fr>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git.adoc |   8 ++++\n environment.h          |   1 +\n refs.c                 |  57 ++++++++++++++++++++++-\n t/meson.build          |   1 +\n t/t1423-ref-backend.sh | 121 +++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 187 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git.adoc b/Documentation/git.adoc\nindex ce099e78b8..8c6a3f6042 100644\n--- a/Documentation/git.adoc\n+++ b/Documentation/git.adoc\n@@ -584,6 +584,14 @@ double-quotes and respecting backslash escapes. E.g., the value\n \trepositories will be set to this value. The default is \"files\".\n \tSee `--ref-format` in linkgit:git-init[1].\n \n+`GIT_REF_URI`::\n+    Specify which reference backend to be used along with its URI. Reference\n+    backends like the files, reftable backend use the $GIT_DIR as their URI.\n++\n+Expects the format `<ref_backend>://<URI-for-resource>`, where the\n+_<ref_backend>_ specifies the reference backend and the _<URI-for-resource>_\n+specifies the URI used by the backend.\n+\n Git Commits\n ~~~~~~~~~~~\n `GIT_AUTHOR_NAME`::\ndiff --git a/environment.h b/environment.h\nindex 51898c99cd..9bc380bba4 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -42,6 +42,7 @@\n #define GIT_OPTIONAL_LOCKS_ENVIRONMENT \"GIT_OPTIONAL_LOCKS\"\n #define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT \"GIT_TEXTDOMAINDIR\"\n #define GIT_ATTR_SOURCE_ENVIRONMENT \"GIT_ATTR_SOURCE\"\n+#define GIT_REF_URI_ENVIRONMENT \"GIT_REF_URI\"\n \n /*\n  * Environment variable used to propagate the --no-advice global option to the\ndiff --git a/refs.c b/refs.c\nindex 23f46867f2..da76e0c54a 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2186,15 +2186,70 @@ static struct ref_store *get_ref_store_for_dir(struct repository *r,\n \treturn maybe_debug_wrap_ref_store(dir, ref_store);\n }\n \n+static struct ref_store *get_ref_store_from_uri(struct repository *repo,\n+\t\t\t\t\t\tconst char *uri)\n+{\n+\tstruct string_list ref_backend_info = STRING_LIST_INIT_DUP;\n+\tenum ref_storage_format format;\n+\tstruct ref_store *store = NULL;\n+\tchar *format_string;\n+\tchar *dir;\n+\n+\tif (!uri) {\n+\t\terror(_(\"reference backend uri is not provided\"));\n+\t\tgoto cleanup;\n+\t}\n+\n+\tif (string_list_split(&ref_backend_info, uri, \":\", 2) != 2) {\n+\t\terror(_(\"invalid reference backend uri format '%s'\"), uri);\n+\t\tgoto cleanup;\n+\t}\n+\n+\tformat_string = ref_backend_info.items[0].string;\n+\tif (!starts_with(ref_backend_info.items[1].string, \"//\")) {\n+\t\terror(_(\"invalid reference backend uri format '%s'\"), uri);\n+\t\tgoto cleanup;\n+\t}\n+\tdir = ref_backend_info.items[1].string + 2;\n+\n+\tif (!dir[0]) {\n+\t\terror(_(\"invalid path in uri '%s'\"), uri);\n+\t\tgoto cleanup;\n+\t}\n+\n+\tformat = ref_storage_format_by_name(format_string);\n+\tif (format == REF_STORAGE_FORMAT_UNKNOWN) {\n+\t\terror(_(\"unknown reference backend '%s'\"), format_string);\n+\t\tgoto cleanup;\n+\t}\n+\n+\tstore = get_ref_store_for_dir(repo, dir, format);\n+\n+cleanup:\n+\tstring_list_clear(&ref_backend_info, 0);\n+\treturn store;\n+}\n+\n struct ref_store *get_main_ref_store(struct repository *r)\n {\n+\tchar *ref_uri;\n+\n \tif (r->refs_private)\n \t\treturn r->refs_private;\n \n \tif (!r->gitdir)\n \t\tBUG(\"attempting to get main_ref_store outside of repository\");\n \n-\tr->refs_private = get_ref_store_for_dir(r, r->gitdir, r->ref_storage_format);\n+\tref_uri = getenv(GIT_REF_URI_ENVIRONMENT);\n+\tif (ref_uri) {\n+\t\tr->refs_private = get_ref_store_from_uri(r, ref_uri);\n+\t\tif (!r->refs_private)\n+\t\t\tdie(\"failed to initialize ref store from URI: %s\", ref_uri);\n+\n+\t} else {\n+\t\tr->refs_private = get_ref_store_for_dir(r, r->gitdir,\n+\t\t\t\t\t\t\tr->ref_storage_format);\n+\t}\n \treturn r->refs_private;\n }\n \ndiff --git a/t/meson.build b/t/meson.build\nindex a5531df415..a66f8fafff 100644\n--- a/t/meson.build\n+++ b/t/meson.build\n@@ -208,6 +208,7 @@ integration_tests = [\n   't1420-lost-found.sh',\n   't1421-reflog-write.sh',\n   't1422-show-ref-exists.sh',\n+  't1423-ref-backend.sh',\n   't1430-bad-ref-name.sh',\n   't1450-fsck.sh',\n   't1451-fsck-buffer.sh',\ndiff --git a/t/t1423-ref-backend.sh b/t/t1423-ref-backend.sh\nnew file mode 100755\nindex 0000000000..f36125bf64\n--- /dev/null\n+++ b/t/t1423-ref-backend.sh\n@@ -0,0 +1,121 @@\n+#!/bin/sh\n+\n+test_description='Test different reference backend URIs'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'empty uri provided' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init --ref-format=files repo &&\n+\t(\n+\t\tcd repo &&\n+\t\tGIT_REF_URI=\"\" &&\n+\t\texport GIT_REF_URI &&\n+\t\ttest_must_fail git refs list 2>err &&\n+\t\ttest_grep \"invalid reference backend uri format\" err\n+\t)\n+'\n+\n+test_expect_success 'invalid uri provided' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init --ref-format=files repo &&\n+\t(\n+\t\tcd repo &&\n+\t\tGIT_REF_URI=\"reftable@/home/reftable\" &&\n+\t\texport GIT_REF_URI &&\n+\t\ttest_must_fail git refs list 2>err &&\n+\t\ttest_grep \"invalid reference backend uri format\" err\n+\t)\n+'\n+\n+test_expect_success 'empty path in uri' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init --ref-format=files repo &&\n+\t(\n+\t\tcd repo &&\n+\t\tGIT_REF_URI=\"reftable://\" &&\n+\t\texport GIT_REF_URI &&\n+\t\ttest_must_fail git refs list 2>err &&\n+\t\ttest_grep \"invalid path in uri\" err\n+\t)\n+'\n+\n+test_expect_success 'uri ends at colon' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init --ref-format=files repo &&\n+\t(\n+\t\tcd repo &&\n+\t\tGIT_REF_URI=\"reftable:\" &&\n+\t\texport GIT_REF_URI &&\n+\t\ttest_must_fail git refs list 2>err &&\n+\t\ttest_grep \"invalid reference backend uri format\" err\n+\t)\n+'\n+\n+test_expect_success 'unknown reference backend' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init --ref-format=files repo &&\n+\t(\n+\t\tcd repo &&\n+\t\tGIT_REF_URI=\"db://.git\" &&\n+\t\texport GIT_REF_URI &&\n+\t\ttest_must_fail git refs list 2>err &&\n+\t\ttest_grep \"unknown reference backend\" err\n+\t)\n+'\n+\n+ref_formats=\"files reftable\"\n+for from_format in $ref_formats\n+do\n+\tfor to_format in $ref_formats\n+\tdo\n+\t\tif test \"$from_format\" = \"$to_format\"\n+\t\tthen\n+\t\t\tcontinue\n+\t\tfi\n+\n+\t\ttest_expect_success \"read from $to_format backend\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\t(\n+\t\t\t\tcd repo &&\n+\t\t\t\ttest_commit 1 &&\n+\t\t\t\ttest_commit 2 &&\n+\t\t\t\ttest_commit 3 &&\n+\n+\t\t\t\tgit refs migrate --dry-run --ref-format=$to_format >out &&\n+\t\t\t\tBACKEND_PATH=$(cat out | sed \"s/.* ${SQ}\\(.*\\)${SQ}/\\1/\") &&\n+\t\t\t\tgit refs list >expect &&\n+\t\t\t\tGIT_REF_URI=\"$to_format://$BACKEND_PATH\" git refs list >actual &&\n+\t\t\t\ttest_cmp expect actual\n+\t\t\t)\n+\t\t'\n+\n+\t\ttest_expect_success \"write to $to_format backend\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\t(\n+\t\t\t\tcd repo &&\n+\t\t\t\ttest_commit 1 &&\n+\t\t\t\ttest_commit 2 &&\n+\t\t\t\ttest_commit 3 &&\n+\n+\t\t\t\tgit refs migrate --dry-run --ref-format=$to_format >out &&\n+\t\t\t\tgit refs list >expect &&\n+\n+\t\t\t\tBACKEND_PATH=$(cat out | sed \"s/.* ${SQ}\\(.*\\)${SQ}/\\1/\") &&\n+\t\t\t\tGIT_REF_URI=\"$to_format://$BACKEND_PATH\" git tag -d 1 &&\n+\n+\t\t\t\tgit refs list >actual &&\n+\t\t\t\ttest_cmp expect actual &&\n+\n+\t\t\t\tGIT_REF_URI=\"$to_format://$BACKEND_PATH\" git refs list >expect &&\n+\t\t\t\tgit refs list >out &&\n+\t\t\t\tcat out | grep -v \"refs/tags/1\" >actual &&\n+\t\t\t\ttest_cmp expect actual\n+\t\t\t)\n+\t\t'\n+\tdone\n+done\n+\n+test_done\n\n-- \n2.51.2\n\n"},{"id":"533058","messageId":"aVvVAH1eRxGa60Fp@pks.im","threadId":"64562","inReplyTo":"20251201-kn-alternate-ref-dir-v3-0-c11b946bc2fa@gmail.com","subject":"Re: [PATCH v3 0/2] refs: allow setting the reference directory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-05T15:13:04Z","receivedAt":"2026-01-05T15:13:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Dec 01, 2025 at 12:24:57PM +0100, Karthik Nayak wrote:\n> Changes in v3:\n> - Cleanup some stale code which wasn't removed.\n> - Localize strings which will be output to the user.\n> - Remove additional defensive checks which are not needed.\n> - Link to v2: https://patch.msgid.link/20251126-kn-alternate-ref-dir-v2-0-8b9f6f18f635@gmail.com\n\nFYI: I did an internal review of this at [1] and mentioned a couple of\nthings that I think still need to be iterated on. Most importantly, I\nthink that we also need to handle worktrees:\n\n    I think we need to do something about worktree ref stores in the\n    context of this series, as we're now thinking a bit broader than\n    before. It would be somewhat weird if you can change the main\n    reference store, but it doesn't have any influence on the worktree\n    ref stores. If I say e.g. that the ref store is located in\n    `/tmp/dir`, then I'd expect that the main ref store would be in\n    `/tmp/dir/refs` and that worktree refs are in\n    `/tmp/dir/worktrees/$name/refs`.\n\n    The reason I think this needs to be handled as part of this MR is\n    that we are extending semantics of the extension now. This is only\n    possible because the extensions are quite strict now, and thus we\n    can strictly extend them. But once we have extended them we cannot\n    just alter their semantics to also cover worktree refs.\n\nSo you can expect another iteration of this patch series once folks\nsettle into their usual post-holiday rhythms again :)\n\nPatrick\n\n[1]: https://gitlab.com/gitlab-org/git/-/merge_requests/451\n"},{"id":"533075","messageId":"CAOLa=ZT5YwDXEs=wHqVcHqLNxen51-hucaPXOWQEMug3oWfxOA@mail.gmail.com","threadId":"64562","inReplyTo":"aVvVAH1eRxGa60Fp@pks.im","subject":"Re: [PATCH v3 0/2] refs: allow setting the reference directory","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2026-01-05T20:13:18Z","receivedAt":"2026-01-05T20:13:20Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Mon, Dec 01, 2025 at 12:24:57PM +0100, Karthik Nayak wrote:\n>> Changes in v3:\n>> - Cleanup some stale code which wasn't removed.\n>> - Localize strings which will be output to the user.\n>> - Remove additional defensive checks which are not needed.\n>> - Link to v2: https://patch.msgid.link/20251126-kn-alternate-ref-dir-v2-0-8b9f6f18f635@gmail.com\n>\n> FYI: I did an internal review of this at [1] and mentioned a couple of\n> things that I think still need to be iterated on. Most importantly, I\n> think that we also need to handle worktrees:\n>\n>     I think we need to do something about worktree ref stores in the\n>     context of this series, as we're now thinking a bit broader than\n>     before. It would be somewhat weird if you can change the main\n>     reference store, but it doesn't have any influence on the worktree\n>     ref stores. If I say e.g. that the ref store is located in\n>     `/tmp/dir`, then I'd expect that the main ref store would be in\n>     `/tmp/dir/refs` and that worktree refs are in\n>     `/tmp/dir/worktrees/$name/refs`.\n>\n>     The reason I think this needs to be handled as part of this MR is\n>     that we are extending semantics of the extension now. This is only\n>     possible because the extensions are quite strict now, and thus we\n>     can strictly extend them. But once we have extended them we cannot\n>     just alter their semantics to also cover worktree refs.\n>\n> So you can expect another iteration of this patch series once folks\n> settle into their usual post-holiday rhythms again :)\n>\n> Patrick\n>\n> [1]: https://gitlab.com/gitlab-org/git/-/merge_requests/451\n\nThanks for putting that here. I did reply to one of Junio's what's\ncooking emails [1] stating the same (mostly that I'm on vacation) and that\nthe topic isn't abandoned but would be delayed.\n\nI've been looking at this with a fresh set of eyes post vacation. One of\nthe things I still need to solve is around how this works with Git\ndirectory detection.\n\nThe current implementation works because it hijacks the refs\ninitialization to set the new reference directory. But this assumes that\nthe repository has a 'refs/' folder and 'HEAD' file within the $GITDIR.\n\nSo if we want this to work with worktrees the way that Patrick\nmentioned, we'd have to create the worktree reference path within the\nprovided reference storage path. But this would mean that the $GITDIR\nfor the worktree wouldn't be initialized with the required files\ncurrently required for being a valid Git directory.\n\nThe issue is that config parsing is only done post Git directory\ndetection. One hacky fix is to create a dummy 'refs/' folder and 'HEAD'\nfile within the $GITDIR, similar to how the 'reftable does it. I'm not a\nbig fan of adding something like that. Would be curious if anyone has\nfurther thoughts on this.\n\n[1]: https://lore.kernel.org/git/CAOLa=ZTeEEntiQdCnDd6B8a_ppJrrZqdURhQJV=bNktnp0JqMw@mail.gmail.com/\n"},{"id":"534294","messageId":"xmqqbjioxahm.fsf@gitster.g","threadId":"64562","inReplyTo":"CAOLa=ZT5YwDXEs=wHqVcHqLNxen51-hucaPXOWQEMug3oWfxOA@mail.gmail.com","subject":"Re: [PATCH v3 0/2] refs: allow setting the reference directory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-20T21:03:33Z","receivedAt":"2026-01-20T21:03:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n>> FYI: I did an internal review of this at [1] and mentioned a couple of\n>> things that I think still need to be iterated on. Most importantly, I\n>> think that we also need to handle worktrees:\n>> ...\n>> So you can expect another iteration of this patch series once folks\n>> settle into their usual post-holiday rhythms again :)\n>>\n>> Patrick\n>>\n>> [1]: https://gitlab.com/gitlab-org/git/-/merge_requests/451\n>\n> Thanks for putting that here. I did reply to one of Junio's what's\n> cooking emails [1] stating the same (mostly that I'm on vacation) and that\n> the topic isn't abandoned but would be delayed.\n\nOK.  The topic has been marked as [Stalled] and I'll probably eject\nit from 'seen' soonish to declutter my tree, but it does not mean a\nrenewed effort on the same topic is unwelcome.  \"Dismissed without\nprejudice\" so to speak.\n\nThanks.\n"},{"id":"534449","messageId":"CAOLa=ZQBvrf_T5BHdam74JBgNZ=WPVAznT3q+f9SvN3Gr9KxAg@mail.gmail.com","threadId":"64562","inReplyTo":"xmqqbjioxahm.fsf@gitster.g","subject":"Re: [PATCH v3 0/2] refs: allow setting the reference directory","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2026-01-22T12:36:05Z","receivedAt":"2026-01-22T12:36:07Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>>> FYI: I did an internal review of this at [1] and mentioned a couple of\n>>> things that I think still need to be iterated on. Most importantly, I\n>>> think that we also need to handle worktrees:\n>>> ...\n>>> So you can expect another iteration of this patch series once folks\n>>> settle into their usual post-holiday rhythms again :)\n>>>\n>>> Patrick\n>>>\n>>> [1]: https://gitlab.com/gitlab-org/git/-/merge_requests/451\n>>\n>> Thanks for putting that here. I did reply to one of Junio's what's\n>> cooking emails [1] stating the same (mostly that I'm on vacation) and that\n>> the topic isn't abandoned but would be delayed.\n>\n> OK.  The topic has been marked as [Stalled] and I'll probably eject\n> it from 'seen' soonish to declutter my tree, but it does not mean a\n> renewed effort on the same topic is unwelcome.  \"Dismissed without\n> prejudice\" so to speak.\n>\n> Thanks.\n\nYeah I understand, I'm still working on it, but it has been a while.\n\nThanks\n"}]}