Skip to content

Commit d0b9457

Browse files
pks-tgitster
authored andcommitted
BreakingChanges: announce switch to "reftable" format
The "reftable" format has come a long way and has matured nicely since it has been merged into git via 57db2a0 (refs: introduce reftable backend, 2024-02-07). It fixes longstanding issues that cannot be fixed with the "files" format in a backwards-compatible way and performs significantly better in many use cases. Announce that we will switch to the "reftable" format in Git 3.0 for newly created repositories and wire up the change, hidden behind the WITH_BREAKING_CHANGES preprocessor define. This switch is dependent on support in the larger Git ecosystem. Most importantly, libraries like JGit, libgit2 and Gitoxide should support the reftable backend so that we don't break all applications and tools built on top of those libraries. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 83014dc commit d0b9457

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

Documentation/BreakingChanges.adoc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,53 @@ Cf. <[email protected]>,
118118
119119
<CA+EOSBncr=4a4d8n9xS4FNehyebpmX8JiUwCsXD47EQDE+DiUQ@mail.gmail.com>.
120120

121+
* The default storage format for references in newly created repositories will
122+
be changed from "files" to "reftable". The "reftable" format provides
123+
multiple advantages over the "files" format:
124+
+
125+
** It is impossible to store two references that only differ in casing on
126+
case-insensitive filesystems with the "files" format. This issue is common
127+
on Windows and macOS platforms. As the "reftable" backend does not use
128+
filesystem paths to encode reference names this problem goes away.
129+
** Similarly, macOS normalizes path names that contain unicode characters,
130+
which has the consequence that you cannot store two names with unicode
131+
characters that are encoded differently with the "files" backend. Again,
132+
this is not an issue with the "reftable" backend.
133+
** Deleting references with the "files" backend requires Git to rewrite the
134+
complete "packed-refs" file. In large repositories with many references
135+
this file can easily be dozens of megabytes in size, in extreme cases it
136+
may be gigabytes. The "reftable" backend uses tombstone markers for
137+
deleted references and thus does not have to rewrite all of its data.
138+
** Repository housekeeping with the "files" backend typically performs
139+
all-into-one repacks of references. This can be quite expensive, and
140+
consequently housekeeping is a tradeoff between the number of loose
141+
references that accumulate and slow down operations that read references,
142+
and compressing those loose references into the "packed-refs" file. The
143+
"reftable" backend uses geometric compaction after every write, which
144+
amortizes costs and ensures that the backend is always in a
145+
well-maintained state.
146+
** Operations that write multiple references at once are not atomic with the
147+
"files" backend. Consequently, Git may see in-between states when it reads
148+
references while a reference transaction is in the process of being
149+
committed to disk.
150+
** Writing many references at once is slow with the "files" backend because
151+
every reference is created as a separate file. The "reftable" backend
152+
significantly outperforms the "files" backend by multiple orders of
153+
magnitude.
154+
** The reftable backend uses a binary format with prefix compression for
155+
reference names. As a result, the format uses less space compared to the
156+
"packed-refs" file.
157+
+
158+
Users that get immediate benefit from the "reftable" backend could continue to
159+
opt-in to the "reftable" format manually by setting the "init.defaultRefFormat"
160+
config. But defaults matter, and we think that overall users will have a better
161+
experience with less platform-specific quirks when they use the new backend by
162+
default.
163+
+
164+
A prerequisite for this change is that the ecosystem is ready to support the
165+
"reftable" format. Most importantly, alternative implementations of Git like
166+
JGit, libgit2 and Gitoxide need to support it.
167+
121168
=== Removals
122169

123170
* Support for grafting commits has long been superseded by git-replace(1).

help.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,8 @@ void get_version_info(struct strbuf *buf, int show_build_options)
810810
SHA1_UNSAFE_BACKEND);
811811
#endif
812812
strbuf_addf(buf, "SHA-256: %s\n", SHA256_BACKEND);
813+
strbuf_addf(buf, "default-ref-format: %s\n",
814+
ref_storage_format_to_name(REF_STORAGE_FORMAT_DEFAULT));
813815
}
814816
}
815817

repository.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ enum ref_storage_format {
2020
REF_STORAGE_FORMAT_REFTABLE,
2121
};
2222

23+
#ifdef WITH_BREAKING_CHANGES /* Git 3.0 */
24+
# define REF_STORAGE_FORMAT_DEFAULT REF_STORAGE_FORMAT_REFTABLE
25+
#else
26+
# define REF_STORAGE_FORMAT_DEFAULT REF_STORAGE_FORMAT_FILES
27+
#endif
28+
2329
struct repo_path_cache {
2430
char *squash_msg;
2531
char *merge_msg;

setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,6 +2541,8 @@ static void repository_format_configure(struct repository_format *repo_fmt,
25412541
repo_fmt->ref_storage_format = ref_format;
25422542
} else if (cfg.ref_format != REF_STORAGE_FORMAT_UNKNOWN) {
25432543
repo_fmt->ref_storage_format = cfg.ref_format;
2544+
} else {
2545+
repo_fmt->ref_storage_format = REF_STORAGE_FORMAT_DEFAULT;
25442546
}
25452547
repo_set_ref_storage_format(the_repository, repo_fmt->ref_storage_format);
25462548
}

t/t0001-init.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,17 @@ test_expect_success 'init warns about invalid init.defaultRefFormat' '
658658
test_cmp expected actual
659659
'
660660

661+
test_expect_success 'default ref format' '
662+
test_when_finished "rm -rf refformat" &&
663+
(
664+
sane_unset GIT_DEFAULT_REF_FORMAT &&
665+
git init refformat
666+
) &&
667+
git version --build-options | sed -ne "s/^default-ref-format: //p" >expect &&
668+
git -C refformat rev-parse --show-ref-format >actual &&
669+
test_cmp expect actual
670+
'
671+
661672
backends="files reftable"
662673
for format in $backends
663674
do

0 commit comments

Comments
 (0)