git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v8 0/6] refs: allow setting the reference directory

From
Karthik Nayak <karthik.188@gmail.com>
Date
Feb 23, 2026, 08:01 UTC
Message-ID
<20260223-kn-alternate-ref-dir-v8-0-0509c132a203@gmail.com>
In-Reply-To
<20251119-kn-alternate-ref-dir-v1-0-4cf4a94c8bed@gmail.com>

While Git allows users to select different reference backends, unlike with objects, there is no flexibility in selecting the reference directory. Currently, the reference format is obtained from the config of the repository and the reference directory is set to the $GIT_DIR.

This patch extends the config 'extensions.refStorage' to take in multiple forms of inputs:

  - A format name alone (e.g., `reftable` or `files`).
  - A URI format `<format>://<payload>` explicitly specifies both the
    format and payload (e.g., `reftable:///foo/bar`).

We also add in a new ENV variable GIT_REFERENCE_BACKEND which can be used to override the config.

One use case for this is migration between different backends. On the server side, migrating from the files backend to the newly introduced reftable backend can be achieved by running 'git refs migrate'. However, for large repositories with millions of references, this migration can take from seconds to minutes.

For some background, at GitLab, the criteria for our migration was to reduce the downtime of the migrate ideally to zero. So running 'git refs migrate --ref-format=reftable' by itself wouldn't work, since it scales with the number of references and we have repos with millions of references, so we need to migrate without loosing any information. We came up with the following plan:

  1. Run git-pack-refs(1) and note timestamp of the generated packed-refs
     file.
  2. Run git refs migrate –dry-run.
  3. If there are no ongoing reference requests (read/write)
     a. Lock the repository by blocking incoming requests (done on a
        layer above git, in Gitaly [1]).
     b. If the timestamp of the packed-refs file has changed, unlock
        the repo and repeat from step 1.
     c. Apply all the loose refs to the dry-run reftable folder (this
        requires support in Git to write refs to arbitrary folder).
     d. Move the reftable dry-run folder into the GIT_DIR.
     e. Swap the repo config
     f. Unlock repo access

Using such a route, scales much better since we only have to worry about blocking the repository by O(ref written between #1 and #3a) and not O(refs in repo). But for doing so, we need to be able to write to a arbitrary reference backend + path. This is to add the missing references to the dry-run reftable folder. This series, achieves that.

Since there was a long gap between v3 <> v4, the version 4 onward is based on top of 2258446484 (RelNotes: correct "fast-import" option name, 2026-01-30).

[1]: https://gitlab.com/gitlab-org/gitaly
---
Changes in v8:
- Fix a typo/grammar in commit 4.
- In the final commits tests, avoid creating a file for text
  comparison.
- Link to v7: https://patch.msgid.link/20260219-kn-alternate-ref-dir-v7-0-16f27860dbdf@gmail.com
Changes in v7:
- Add more details in the commit messages.
- Cleanup some whitespace.
- Reorder the commits to be group related changes together.
- Add checks for stubs in the tests when creating new repos.
- Link to v6: https://patch.msgid.link/20260214-kn-alternate-ref-dir-v6-0-86a82c77cf59@gmail.com
Changes in v6:
- The biggest change in this version is that we now support using the
  environment variable with 'git-clone(1)' and 'git-init(1)'. In such
  situations, the alternate reference directory is created and the
  config is added to the repository.
- Add a new commit which moves stub creation/removal to the generic
  layer.
- Cleanup logic flow in `refs_compute_filesystem_location()`.
- Add more tests for usage with 'git-clone(1)', 'git-init(1)' and
  migration of repositories using alternate refs backend.
- Fixup documentation, commit messages and typos.
- Link to v5: https://patch.msgid.link/20260209-kn-alternate-ref-dir-v5-0-740899834ceb@gmail.com
Changes in v5:
- Moved around the commits, to ensure that the code to handle the config
  in the backend is first. Previously, we added the config first, which
  meant the commit allowed users to provide a URI but it was simply
  ignore.
- Fix typos and grammar and rename variables.
- Clean up the description and documentation to actually specify
  protocol over location.
- Avoid an extra memory allocation by detaching the strbuf value.
- Link to v4: https://patch.msgid.link/20260202-kn-alternate-ref-dir-v4-0-3b30430411e3@gmail.com
Changes in v4:
- Mostly re-wrote the code to also support worktree. Now, the existing
  backends will store worktree references in 'ref_dir/worktrees/wt_id'
  and add corresponding stubs in 'git_dir/worktrees/wt_id'.
- We also support relative paths in the reference directories. These
  relative paths are resolved relative to the GIT_DIR.
- Link to v3: https://patch.msgid.link/20251201-kn-alternate-ref-dir-v3-0-c11b946bc2fa@gmail.com
Changes in v3:
- Cleanup some stale code which wasn't removed.
- Localize strings which will be output to the user.
- Remove additional defensive checks which are not needed.
- Link to v2: https://patch.msgid.link/20251126-kn-alternate-ref-dir-v2-0-8b9f6f18f635@gmail.com
Changes in v2:
- Added more clarification and proper intent in the cover message.
- Changed the format from '<ref_backend>://<path>' to
  `<ref_backend>://<URI-for-resource>` as it much clearer.
- Added logic to check for the '//' in the provided URI and a test for
  the same.
- In the tests:
  - Use test_must_fail() instead of ! git
  - Fix looped tests not using the variables correctly and ensure that
    the test description is correct.
- Link to v1: https://patch.msgid.link/20251119-kn-alternate-ref-dir-v1-0-4cf4a94c8bed@gmail.com
---
 Documentation/config/extensions.adoc |  16 +-
 Documentation/git.adoc               |   5 +
 builtin/clone.c                      |   9 +-
 builtin/worktree.c                   |  34 +++++
 environment.h                        |   1 +
 refs.c                               | 126 +++++++++++++++-
 refs.h                               |  13 ++
 refs/files-backend.c                 |  23 ++-
 refs/packed-backend.c                |   5 +
 refs/packed-backend.h                |   1 +
 refs/refs-internal.h                 |  14 ++
 refs/reftable-backend.c              |  61 ++------
 repository.c                         |   9 +-
 repository.h                         |   8 +-
 setup.c                              |  96 ++++++++++--
 setup.h                              |   4 +-
 t/meson.build                        |   1 +
 t/t1423-ref-backend.sh               | 280 +++++++++++++++++++++++++++++++++++
 18 files changed, 625 insertions(+), 81 deletions(-)
Karthik Nayak (6):
      setup: don't modify repo in `create_reference_database()`
      refs: extract out `refs_create_refdir_stubs()`
      refs: move out stub modification to generic layer
      refs: receive and use the reference storage payload
      refs: allow reference location in refstorage config
      refs: add GIT_REFERENCE_BACKEND to specify reference backend
Range-diff versus v7:
1:  0f9fad1145 = 1:  8cc4b88f60 setup: don't modify repo in `create_reference_database()`
2:  cfe28f7464 = 2:  382b7b1964 refs: extract out `refs_create_refdir_stubs()`
3:  7a08fde968 = 3:  ef00e85466 refs: move out stub modification to generic layer
4:  b6988bf969 ! 4:  3e7d7042ef refs: receive and use the reference storage payload
    @@ refs/refs-internal.h: enum ref_transaction_error refs_verify_refnames_available(
     + * directory if working with a linked worktree. If working with the main
     + * worktree, both values will be the same.
     + *
    -+ * This is used by backends that store store files in the repository directly.
    ++ * This is used by backends that store references in the repository directly.
     + */
     +void refs_compute_filesystem_location(const char *gitdir, const char *payload,
     +				      bool *is_worktree, struct strbuf *refdir,
5:  4769fae36f = 5:  5b69104cd9 refs: allow reference location in refstorage config
6:  6bc3f09144 ! 6:  6a007df2ad refs: add GIT_REFERENCE_BACKEND to specify reference backend
    @@ t/t1423-ref-backend.sh: run_with_uri() {
     +	refdir=$2 &&
     +
     +	# verify that the stubs were added to the $GITDIR.
    -+	cat $gitdir/refs/heads >actual &&
     +	echo "repository uses alternate refs storage" >expect &&
    -+	test_cmp expect actual &&
    -+	cat $gitdir/HEAD >actual &&
    ++	test_cmp expect $gitdir/refs/heads &&
     +	echo "ref: refs/heads/.invalid" >expect &&
    -+	test_cmp expect actual
    ++	test_cmp expect $gitdir/HEAD
     +
     +	# verify that backend specific files exist.
     +	case "$GIT_DEFAULT_REF_FORMAT" in

base-commit: 22584464849815268419fd9d2eba307362360db1 change-id: 20251105-kn-alternate-ref-dir-3e572e8cd0ef

Thanks
- Karthik
Previous: Karthik NayakNext: Karthik Nayak
Message 77 of 101 in “refs: allow setting the reference directory”
  1. 0/2 refs: allow setting the reference directoryKarthik Nayak, Nov 19, 2025
  2. 1/2 refs: support obtaining ref_store for given dirKarthik Nayak, Nov 19, 2025
  3. Justin ToblerNov 20, 2025
  4. Karthik NayakNov 21, 2025
  5. 2/2 refs: add GIT_REF_URI to specify reference backend and directoryKarthik Nayak, Nov 19, 2025
  6. Eric SunshineNov 19, 2025
  7. Karthik NayakNov 19, 2025
  8. Jean-Noël AvilaNov 20, 2025
  9. Karthik NayakNov 21, 2025
  10. Justin ToblerNov 20, 2025
  11. Karthik NayakNov 24, 2025
  12. Toon ClaesNov 21, 2025
  13. Junio C HamanoNov 21, 2025
  14. Karthik NayakNov 24, 2025
  15. Toon ClaesNov 26, 2025
  16. Karthik NayakNov 24, 2025
  17. Patrick SteinhardtDec 1, 2025
  18. Karthik NayakDec 2, 2025
  19. Junio C HamanoNov 23, 2025
  20. Patrick SteinhardtDec 1, 2025
  21. Junio C HamanoDec 2, 2025
  22. Karthik NayakDec 2, 2025
  23. 0/4 refs: allow setting the reference directoryKarthik Nayak, Feb 2, 2026
  24. 1/4 refs: allow reference location in refstorage configKarthik Nayak, Feb 2, 2026
  25. Patrick SteinhardtFeb 6, 2026
  26. Karthik NayakFeb 9, 2026
  27. 2/4 refs: extract out `refs_create_refdir_stubs()`Karthik Nayak, Feb 2, 2026
  28. Patrick SteinhardtFeb 6, 2026
  29. Karthik NayakFeb 9, 2026
  30. 3/4 refs: parse and use the reference storage payloadKarthik Nayak, Feb 2, 2026
  31. Patrick SteinhardtFeb 6, 2026
  32. Karthik NayakFeb 9, 2026
  33. 4/4 refs: add GIT_REFERENCE_BACKEND to specify reference backendKarthik Nayak, Feb 2, 2026
  34. Patrick SteinhardtFeb 6, 2026
  35. Karthik NayakFeb 9, 2026
  36. Patrick SteinhardtFeb 6, 2026
  37. Junio C HamanoFeb 6, 2026
  38. Karthik NayakFeb 9, 2026
  39. 0/4 refs: allow setting the reference directoryKarthik Nayak, Feb 9, 2026
  40. 1/4 refs: extract out `refs_create_refdir_stubs()`Karthik Nayak, Feb 9, 2026
  41. 2/4 refs: forward and use the reference storage payloadKarthik Nayak, Feb 9, 2026
  42. Patrick SteinhardtFeb 9, 2026
  43. Karthik NayakFeb 10, 2026
  44. Jeff KingFeb 10, 2026
  45. Karthik NayakFeb 13, 2026
  46. Jeff KingFeb 15, 2026
  47. 3/4 refs: allow reference location in refstorage configKarthik Nayak, Feb 9, 2026
  48. Patrick SteinhardtFeb 9, 2026
  49. Karthik NayakFeb 10, 2026
  50. Jeff KingFeb 10, 2026
  51. Karthik NayakFeb 11, 2026
  52. 4/4 refs: add GIT_REFERENCE_BACKEND to specify reference backendKarthik Nayak, Feb 9, 2026
  53. Patrick SteinhardtFeb 9, 2026
  54. Junio C HamanoFeb 9, 2026
  55. Karthik NayakFeb 10, 2026
  56. Junio C HamanoFeb 10, 2026
  57. 0/6 refs: allow setting the reference directoryKarthik Nayak, Feb 14, 2026
  58. 1/6 setup: don't modify repo in `create_reference_database()`Karthik Nayak, Feb 14, 2026
  59. Patrick SteinhardtFeb 17, 2026
  60. Karthik NayakFeb 17, 2026
  61. 2/6 refs: extract out `refs_create_refdir_stubs()`Karthik Nayak, Feb 14, 2026
  62. 3/6 refs: receive and use the reference storage payloadKarthik Nayak, Feb 14, 2026
  63. Patrick SteinhardtFeb 17, 2026
  64. Karthik NayakFeb 17, 2026
  65. 4/6 refs: move out stub modification to generic layerKarthik Nayak, Feb 14, 2026
  66. Patrick SteinhardtFeb 17, 2026
  67. Karthik NayakFeb 17, 2026
  68. Toon ClaesFeb 18, 2026
  69. Karthik NayakFeb 19, 2026
  70. 5/6 refs: allow reference location in refstorage configKarthik Nayak, Feb 14, 2026
  71. 6/6 refs: add GIT_REFERENCE_BACKEND to specify reference backendKarthik Nayak, Feb 14, 2026
  72. Patrick SteinhardtFeb 17, 2026
  73. Karthik NayakFeb 17, 2026
  74. Patrick SteinhardtFeb 17, 2026
  75. Toon ClaesFeb 18, 2026
  76. Karthik NayakFeb 19, 2026
  77. 0/6 refs: allow setting the reference directoryKarthik Nayak, Feb 23, 2026
  78. 1/6 setup: don't modify repo in `create_reference_database()`Karthik Nayak, Feb 23, 2026
  79. 2/6 refs: extract out `refs_create_refdir_stubs()`Karthik Nayak, Feb 23, 2026
  80. 3/6 refs: move out stub modification to generic layerKarthik Nayak, Feb 23, 2026
  81. 4/6 refs: receive and use the reference storage payloadKarthik Nayak, Feb 23, 2026
  82. 5/6 refs: allow reference location in refstorage configKarthik Nayak, Feb 23, 2026
  83. Kristoffer HaugsbakkFeb 23, 2026
  84. Karthik NayakFeb 24, 2026
  85. Kristoffer HaugsbakkFeb 24, 2026
  86. Karthik NayakFeb 24, 2026
  87. 6/6 refs: add GIT_REFERENCE_BACKEND to specify reference backendKarthik Nayak, Feb 23, 2026
  88. Toon ClaesFeb 25, 2026
  89. Karthik NayakFeb 25, 2026
  90. Patrick SteinhardtFeb 23, 2026
  91. Karthik NayakFeb 23, 2026
  92. Junio C HamanoFeb 23, 2026
  93. Karthik NayakFeb 25, 2026
  94. 0/6 refs: allow setting the reference directoryKarthik Nayak, Feb 25, 2026
  95. 1/6 setup: don't modify repo in `create_reference_database()`Karthik Nayak, Feb 25, 2026
  96. 2/6 refs: extract out `refs_create_refdir_stubs()`Karthik Nayak, Feb 25, 2026
  97. 3/6 refs: move out stub modification to generic layerKarthik Nayak, Feb 25, 2026
  98. 4/6 refs: receive and use the reference storage payloadKarthik Nayak, Feb 25, 2026
  99. 5/6 refs: allow reference location in refstorage configKarthik Nayak, Feb 25, 2026
  100. Junio C HamanoFeb 25, 2026
  101. 6/6 refs: add GIT_REFERENCE_BACKEND to specify reference backendKarthik Nayak, Feb 25, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.