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

[PATCH 0/9] refs: ref storage format migrations

From
Patrick Steinhardt <ps@pks.im>
Date
May 23, 2024, 08:25 UTC
Message-ID
<cover.1716451672.git.ps@pks.im>
Hi,

this patch series implements migration of ref storage formats such that it is for example possible to migrate a repository with "files" format to the "reftable" format. The migration logic comes in the form of a new `git refs migrate` subcommand. As mentioned in [1], I do have plans to extend the new git-refs(1) over time.

In the current form, the migration logic has three major limitations:
  - It does not work with repositories that have worktrees as we have to
    migrate multiple ref stores here, one for every worktree. I wanted
    to avoid making this series too complex right from the start.
  - It does not migrate reflogs, because we have no interfaces to do so.
    I want to eventually address this by adding log-only updates to
    transactions.
  - It is not safe with concurrent writers. This is the limitation that
    is most critical in my eyes. The root cause here is that it is
    inherently impossible to lock the "files" backend for writes. I have
    been thinking about this issue a lot and have not found any solution
    that works. There are partial solutions here:
      - Create a central lockfile for the "files" backend -- if there,
        the backend will refuse to write. If that lock needs to be
        acquired during the "commit" phase of transaction though then we
        would essentially start to sequentialize all writes in the
        "files" backend, which is a non-starter. If not, then processes
        which are running already may not have seen it, and thus the
        issue still exists.
     - Pack all loose refs, remove "refs/" and create a "refs.lock"
       file. This isn't safe though because root refs can still be
       written.
     - Create a log of concurrent writes and apply that to the migrated
       refs once done. This is a lot of complexity, and it's unclear
       whether it even solves the issue with already-running writers.
     - Create a temporary "extensions.refMigration" extension that is
       unhandled by Git. New processes will refuse to run in such a
       repo and thus cannot write to it. Again, unsafe with running
       writers.
    Another alternative is that we could just make this a best effort.
    The "reftable" backend supports locking, and for the "files" backend
    we could just lock "HEAD" and call it a day. I'm not sure whether it
    is preferable though to have a "partial" solution compared to having
    none at all, as it may cause users to be less mindful. That's why I
    decided to just have no solution at all and document the limitation
    accordingly.
    If anybody has ideas here I'd be very happy to hear them.

Anyway. The current state of this patch series is sufficient to migrate repos without reflogs and worktrees, and thus mostly applies to bare repositories, only. This is somewhat intentional -- as a server operator this is of course our primary usecase at GitLab. We do plan to also upstream support for writing reflogs though, but in a later step. We do not plan to implement support for migrating repositories with worktrees, but I'd be happy to help out with the effort in case somebody else wants to.

The series is built on top of 4365c6fcf9 (The sixth batch, 2024-05-20). It pulls in the following two dependencies:

  - ps/refs-without-the-repository-updates at 00892786b8 (refs/packed:
    remove references to `the_hash_algo`, 2024-05-17). This is mostly to
    avoid conflicts.
  - ps/pseudo-ref-terminology at 8e4f5c2dc2 (refs: refuse to write
    pseudorefs, 2024-05-15). This is a functional prerequisite because
    the migration logic relies on the new definition of pseudorefs.

There are two minor textual conflicts when merged to "next" or "seen". One is a conflicting added header in "refs/reftable-backend.c", and one is a conflict with added functions in "refs.c". Both of these conflicts are trivial to solve by accepting both sides.

Thanks!
Patrick
[1]: https://lore.kernel.org/git/ZkNJaaKTTKbns8wo@tanuki/#t
Patrick Steinhardt (9):
  setup: unset ref storage when reinitializing repository version
  refs: convert ref storage format to an enum
  refs: pass storage format to `ref_store_init()` explicitly
  refs: allow to skip creation of reflog entries
  refs/files: refactor `add_pseudoref_and_head_entries()`
  refs/files: extract function to iterate through root refs
  refs: implement removal of ref storages
  refs: implement logic to migrate between ref storage formats
  builtin/refs: new command to migrate ref storage formats
 .gitignore                 |   1 +
 Documentation/git-refs.txt |  59 +++++++
 Makefile                   |   1 +
 builtin.h                  |   1 +
 builtin/clone.c            |   2 +-
 builtin/init-db.c          |   2 +-
 builtin/refs.c             |  75 +++++++++
 git.c                      |   1 +
 refs.c                     | 319 +++++++++++++++++++++++++++++++++++--
 refs.h                     |  41 ++++-
 refs/files-backend.c       | 121 ++++++++++++--
 refs/packed-backend.c      |  15 ++
 refs/refs-internal.h       |   7 +
 refs/reftable-backend.c    |  37 ++++-
 repository.c               |   3 +-
 repository.h               |  10 +-
 setup.c                    |  10 +-
 setup.h                    |   9 +-
 t/helper/test-ref-store.c  |   1 +
 t/t1460-refs-migrate.sh    | 243 ++++++++++++++++++++++++++++
 20 files changed, 913 insertions(+), 45 deletions(-)
 create mode 100644 Documentation/git-refs.txt
 create mode 100644 builtin/refs.c
 create mode 100755 t/t1460-refs-migrate.sh
-- 
2.45.1.216.g4365c6fcf9.dirty
Next: Patrick Steinhardt
Message 1 of 103 in “refs: ref storage format migrations”
  1. 0/9 refs: ref storage format migrationsPatrick Steinhardt, May 23, 2024
  2. 1/9 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, May 23, 2024
  3. 2/9 refs: convert ref storage format to an enumPatrick Steinhardt, May 23, 2024
  4. 3/9 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, May 23, 2024
  5. 4/9 refs: allow to skip creation of reflog entriesPatrick Steinhardt, May 23, 2024
  6. 5/9 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, May 23, 2024
  7. 6/9 refs/files: extract function to iterate through root refsPatrick Steinhardt, May 23, 2024
  8. 7/9 refs: implement removal of ref storagesPatrick Steinhardt, May 23, 2024
  9. 8/9 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, May 23, 2024
  10. Eric SunshineMay 23, 2024
  11. Patrick SteinhardtMay 24, 2024
  12. Eric SunshineMay 24, 2024
  13. 9/9 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, May 23, 2024
  14. Eric SunshineMay 23, 2024
  15. Patrick SteinhardtMay 24, 2024
  16. Junio C HamanoMay 23, 2024
  17. Patrick SteinhardtMay 24, 2024
  18. Junio C HamanoMay 24, 2024
  19. Patrick SteinhardtMay 28, 2024
  20. Junio C HamanoMay 28, 2024
  21. 0/9 refs: ref storage format migrationsPatrick Steinhardt, May 24, 2024
  22. 1/9 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, May 24, 2024
  23. Justin ToblerMay 24, 2024
  24. Patrick SteinhardtMay 28, 2024
  25. 2/9 refs: convert ref storage format to an enumPatrick Steinhardt, May 24, 2024
  26. 3/9 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, May 24, 2024
  27. 4/9 refs: allow to skip creation of reflog entriesPatrick Steinhardt, May 24, 2024
  28. 5/9 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, May 24, 2024
  29. 6/9 refs/files: extract function to iterate through root refsPatrick Steinhardt, May 24, 2024
  30. 7/9 refs: implement removal of ref storagesPatrick Steinhardt, May 24, 2024
  31. 8/9 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, May 24, 2024
  32. Justin ToblerMay 24, 2024
  33. Patrick SteinhardtMay 28, 2024
  34. 9/9 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, May 24, 2024
  35. Ramsay JonesMay 24, 2024
  36. Eric SunshineMay 24, 2024
  37. Patrick SteinhardtMay 28, 2024
  38. 00/12 refs: ref storage format migrationsPatrick Steinhardt, May 28, 2024
  39. 01/12 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, May 28, 2024
  40. 02/12 refs: convert ref storage format to an enumPatrick Steinhardt, May 28, 2024
  41. 03/12 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, May 28, 2024
  42. 04/12 refs: allow to skip creation of reflog entriesPatrick Steinhardt, May 28, 2024
  43. 05/12 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, May 28, 2024
  44. 06/12 refs/files: extract function to iterate through root refsPatrick Steinhardt, May 28, 2024
  45. 07/12 refs/files: fix NULL pointer deref when releasing ref storePatrick Steinhardt, May 28, 2024
  46. 08/12 reftable: inline `merged_table_release()`Patrick Steinhardt, May 28, 2024
  47. 09/12 worktree: don't store main worktree twicePatrick Steinhardt, May 28, 2024
  48. 10/12 refs: implement removal of ref storagesPatrick Steinhardt, May 28, 2024
  49. 11/12 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, May 28, 2024
  50. 12/12 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, May 28, 2024
  51. Junio C HamanoMay 31, 2024
  52. Junio C HamanoJun 2, 2024
  53. Patrick SteinhardtJun 3, 2024
  54. Junio C HamanoMay 28, 2024
  55. Junio C HamanoMay 28, 2024
  56. 00/12 refs: ref storage migrationsPatrick Steinhardt, Jun 3, 2024
  57. 01/12 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, Jun 3, 2024
  58. 02/12 refs: convert ref storage format to an enumPatrick Steinhardt, Jun 3, 2024
  59. 03/12 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, Jun 3, 2024
  60. Karthik NayakJun 4, 2024
  61. 04/12 refs: allow to skip creation of reflog entriesPatrick Steinhardt, Jun 3, 2024
  62. Karthik NayakJun 4, 2024
  63. 05/12 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, Jun 3, 2024
  64. 06/12 refs/files: extract function to iterate through root refsPatrick Steinhardt, Jun 3, 2024
  65. Jeff KingJun 5, 2024
  66. Patrick SteinhardtJun 6, 2024
  67. Patrick SteinhardtJun 6, 2024
  68. Patrick SteinhardtJun 6, 2024
  69. 07/12 refs/files: fix NULL pointer deref when releasing ref storePatrick Steinhardt, Jun 3, 2024
  70. 08/12 reftable: inline `merged_table_release()`Patrick Steinhardt, Jun 3, 2024
  71. 09/12 worktree: don't store main worktree twicePatrick Steinhardt, Jun 3, 2024
  72. 10/12 refs: implement removal of ref storagesPatrick Steinhardt, Jun 3, 2024
  73. Karthik NayakJun 4, 2024
  74. Jeff KingJun 5, 2024
  75. Junio C HamanoJun 5, 2024
  76. Patrick SteinhardtJun 6, 2024
  77. 11/12 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, Jun 3, 2024
  78. Karthik NayakJun 4, 2024
  79. Patrick SteinhardtJun 5, 2024
  80. Jeff KingJun 5, 2024
  81. Junio C HamanoJun 5, 2024
  82. Patrick SteinhardtJun 6, 2024
  83. Jeff KingJun 6, 2024
  84. Junio C HamanoJun 6, 2024
  85. Jeff KingJun 8, 2024
  86. Junio C HamanoJun 8, 2024
  87. Patrick SteinhardtJun 6, 2024
  88. 12/12 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, Jun 3, 2024
  89. 00/12 refs: ref storage migrationsPatrick Steinhardt, Jun 6, 2024
  90. 01/12 setup: unset ref storage when reinitializing repository versionPatrick Steinhardt, Jun 6, 2024
  91. 02/12 refs: convert ref storage format to an enumPatrick Steinhardt, Jun 6, 2024
  92. 03/12 refs: pass storage format to `ref_store_init()` explicitlyPatrick Steinhardt, Jun 6, 2024
  93. 04/12 refs: allow to skip creation of reflog entriesPatrick Steinhardt, Jun 6, 2024
  94. 05/12 refs/files: refactor `add_pseudoref_and_head_entries()`Patrick Steinhardt, Jun 6, 2024
  95. 06/12 refs/files: extract function to iterate through root refsPatrick Steinhardt, Jun 6, 2024
  96. 07/12 refs/files: fix NULL pointer deref when releasing ref storePatrick Steinhardt, Jun 6, 2024
  97. 08/12 reftable: inline `merged_table_release()`Patrick Steinhardt, Jun 6, 2024
  98. 09/12 worktree: don't store main worktree twicePatrick Steinhardt, Jun 6, 2024
  99. 10/12 refs: implement removal of ref storagesPatrick Steinhardt, Jun 6, 2024
  100. 11/12 refs: implement logic to migrate between ref storage formatsPatrick Steinhardt, Jun 6, 2024
  101. 12/12 builtin/refs: new command to migrate ref storage formatsPatrick Steinhardt, Jun 6, 2024
  102. Jeff KingJun 6, 2024
  103. Junio C HamanoJun 6, 2024

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.