Git fork

Merge branch 'ps/use-reftable-as-default-in-3.0'

The reftable ref backend has matured enough; Git 3.0 will make it
the default format in a newly created repositories by default.

* ps/use-reftable-as-default-in-3.0:
setup: use "reftable" format when experimental features are enabled
BreakingChanges: announce switch to "reftable" format

+120
+47
Documentation/BreakingChanges.adoc
··· 118 118 <20170223155046.e7nxivfwqqoprsqj@LykOS.localdomain>, 119 119 <CA+EOSBncr=4a4d8n9xS4FNehyebpmX8JiUwCsXD47EQDE+DiUQ@mail.gmail.com>. 120 120 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 + 121 168 === Removals 122 169 123 170 * Support for grafting commits has long been superseded by git-replace(1).
+6
Documentation/config/feature.adoc
··· 24 24 * `pack.usePathWalk` may speed up packfile creation and make the packfiles be 25 25 significantly smaller in the presence of certain filename collisions with Git's 26 26 default name-hash. 27 + + 28 + * `init.defaultRefFormat=reftable` causes newly initialized repositories to use 29 + the reftable format for storing references. This new format solves issues with 30 + case-insensitive filesystems, compresses better and performs significantly 31 + better with many use cases. Refer to Documentation/technical/reftable.adoc for 32 + more information on this new storage format. 27 33 28 34 feature.manyFiles:: 29 35 Enable config options that optimize for repos with many files in the
+2
help.c
··· 810 810 SHA1_UNSAFE_BACKEND); 811 811 #endif 812 812 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)); 813 815 } 814 816 } 815 817
+6
repository.h
··· 20 20 REF_STORAGE_FORMAT_REFTABLE, 21 21 }; 22 22 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 + 23 29 struct repo_path_cache { 24 30 char *squash_msg; 25 31 char *merge_msg;
+14
setup.c
··· 2484 2484 goto out; 2485 2485 } 2486 2486 2487 + /* 2488 + * Enable the reftable format when "features.experimental" is enabled. 2489 + * "init.defaultRefFormat" takes precedence over this setting. 2490 + */ 2491 + if (!strcmp(key, "feature.experimental") && 2492 + cfg->ref_format == REF_STORAGE_FORMAT_UNKNOWN && 2493 + git_config_bool(key, value)) { 2494 + cfg->ref_format = REF_STORAGE_FORMAT_REFTABLE; 2495 + ret = 0; 2496 + goto out; 2497 + } 2498 + 2487 2499 ret = 0; 2488 2500 out: 2489 2501 free(str); ··· 2544 2556 repo_fmt->ref_storage_format = ref_format; 2545 2557 } else if (cfg.ref_format != REF_STORAGE_FORMAT_UNKNOWN) { 2546 2558 repo_fmt->ref_storage_format = cfg.ref_format; 2559 + } else { 2560 + repo_fmt->ref_storage_format = REF_STORAGE_FORMAT_DEFAULT; 2547 2561 } 2548 2562 repo_set_ref_storage_format(the_repository, repo_fmt->ref_storage_format); 2549 2563 }
+45
t/t0001-init.sh
··· 658 658 test_cmp expected actual 659 659 ' 660 660 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 + 661 672 backends="files reftable" 662 673 for format in $backends 663 674 do ··· 734 745 735 746 GIT_DEFAULT_REF_FORMAT=reftable git init refformat && 736 747 echo reftable >expect && 748 + git -C refformat rev-parse --show-ref-format >actual && 749 + test_cmp expect actual 750 + ' 751 + 752 + test_expect_success "init with feature.experimental=true" ' 753 + test_when_finished "rm -rf refformat" && 754 + test_config_global feature.experimental true && 755 + ( 756 + sane_unset GIT_DEFAULT_REF_FORMAT && 757 + git init refformat 758 + ) && 759 + echo reftable >expect && 760 + git -C refformat rev-parse --show-ref-format >actual && 761 + test_cmp expect actual 762 + ' 763 + 764 + test_expect_success "init.defaultRefFormat overrides feature.experimental=true" ' 765 + test_when_finished "rm -rf refformat" && 766 + test_config_global feature.experimental true && 767 + test_config_global init.defaultRefFormat files && 768 + ( 769 + sane_unset GIT_DEFAULT_REF_FORMAT && 770 + git init refformat 771 + ) && 772 + echo files >expect && 773 + git -C refformat rev-parse --show-ref-format >actual && 774 + test_cmp expect actual 775 + ' 776 + 777 + test_expect_success "GIT_DEFAULT_REF_FORMAT= overrides feature.experimental=true" ' 778 + test_when_finished "rm -rf refformat" && 779 + test_config_global feature.experimental true && 780 + GIT_DEFAULT_REF_FORMAT=files git init refformat && 781 + echo files >expect && 737 782 git -C refformat rev-parse --show-ref-format >actual && 738 783 test_cmp expect actual 739 784 '