From c41258359e2f77a4fba000b2bbb975ebaf7d641b Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:32 -0400 Subject: [PATCH 01/10] pack-write.c: plug a leak in stage_tmp_packfiles() The function `stage_tmp_packfiles()` generates a filename to use for staging the contents of what will become the pack's ".mtimes" file. The name is generated in `write_mtimes_file()` and the result is returned back to `stage_tmp_packfiles()` which uses it to rename the temporary file into place via `rename_tmp_packfiles()`. `write_mtimes_file()` returns a `const char *`, indicating that callers are not expected to free its result (similar to, e.g., `oid_to_hex()`). But callers are expected to free its result, so this return type is incorrect. Change the function's signature to return a non-const `char *`, and free it at the end of `stage_tmp_packfiles()`. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- pack-write.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pack-write.c b/pack-write.c index f171405495..4da0ccc5f5 100644 --- a/pack-write.c +++ b/pack-write.c @@ -312,13 +312,13 @@ static void write_mtimes_trailer(struct hashfile *f, const unsigned char *hash) hashwrite(f, hash, the_hash_algo->rawsz); } -static const char *write_mtimes_file(struct packing_data *to_pack, - struct pack_idx_entry **objects, - uint32_t nr_objects, - const unsigned char *hash) +static char *write_mtimes_file(struct packing_data *to_pack, + struct pack_idx_entry **objects, + uint32_t nr_objects, + const unsigned char *hash) { struct strbuf tmp_file = STRBUF_INIT; - const char *mtimes_name; + char *mtimes_name; struct hashfile *f; int fd; @@ -544,7 +544,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer, char **idx_tmp_name) { const char *rev_tmp_name = NULL; - const char *mtimes_tmp_name = NULL; + char *mtimes_tmp_name = NULL; if (adjust_shared_perm(pack_tmp_name)) die_errno("unable to make temporary pack file readable"); @@ -568,6 +568,8 @@ void stage_tmp_packfiles(struct strbuf *name_buffer, rename_tmp_packfile(name_buffer, rev_tmp_name, "rev"); if (mtimes_tmp_name) rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes"); + + free(mtimes_tmp_name); } void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought) From c512f31109ea09a6db72af0af4572dc0a2c2df0f Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:35 -0400 Subject: [PATCH 02/10] builtin/repack.c: fix incorrect reference to '-C' When cruft packs were originally being developed, `-C` was designated as the short-form for `--cruft` (as in `git repack -C`). This was dropped due to confusion with Git's top-level `-C` option before submitting to the list. But the reference to it in `--cruft-expiration`'s help text was never updated. Fix that dangling reference in this patch. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/repack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/repack.c b/builtin/repack.c index df4d8e0f0b..d9eee15c2f 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -774,7 +774,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("same as -a, pack unreachable cruft objects separately"), PACK_CRUFT), OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"), - N_("with -C, expire objects older than this")), + N_("with --cruft, expire objects older than this")), OPT_BOOL('d', NULL, &delete_redundant, N_("remove redundant packs, and run git-prune-packed")), OPT_BOOL('f', NULL, &po_args.no_reuse_delta, From 05b9013b7181e0c842517ce76aeab25a56670dc0 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:38 -0400 Subject: [PATCH 03/10] builtin/gc.c: ignore cruft packs with `--keep-largest-pack` When cruft packs were implemented, we never adjusted the code for `git gc`'s `--keep-largest-pack` and `gc.bigPackThreshold` to ignore cruft packs. This option and configuration option share a common implementation, but including cruft packs is wrong in both cases: - Running `git gc --keep-largest-pack` in a repository where the largest pack is the cruft pack itself will make it impossible for `git gc` to prune objects, since the cruft pack itself is kept. - The same is true for `gc.bigPackThreshold`, if the size of the cruft pack exceeds the limit set by the caller. In the future, it is possible that `gc.bigPackThreshold` could be used to write a separate cruft pack containing any new unreachable objects that entered the repository since the last time a cruft pack was written. There are some complexities to doing so, mainly around handling pruning objects that are in an existing cruft pack that is above the threshold (which would either need to be rewritten, or else delay pruning). Rewriting a substantially similar cruft pack isn't ideal, but it is significantly better than the status-quo. If users have large cruft packs that they don't want to rewrite, they can mark them as `*.keep` packs. But in general, if a repository has a cruft pack that is so large it is slowing down GC's, it should probably be pruned anyway. In the meantime, ignore cruft packs in the common implementation for both of these options, and add a pair of tests to prevent any future regressions here. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- Documentation/config/gc.txt | 10 ++++----- Documentation/git-gc.txt | 7 +++--- builtin/gc.c | 2 +- t/t6500-gc.sh | 43 +++++++++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt index 38fea076a2..8d5353e9e0 100644 --- a/Documentation/config/gc.txt +++ b/Documentation/config/gc.txt @@ -43,11 +43,11 @@ gc.autoDetach:: if the system supports it. Default is true. gc.bigPackThreshold:: - If non-zero, all packs larger than this limit are kept when - `git gc` is run. This is very similar to `--keep-largest-pack` - except that all packs that meet the threshold are kept, not - just the largest pack. Defaults to zero. Common unit suffixes of - 'k', 'm', or 'g' are supported. + If non-zero, all non-cruft packs larger than this limit are kept + when `git gc` is run. This is very similar to + `--keep-largest-pack` except that all non-cruft packs that meet + the threshold are kept, not just the largest pack. Defaults to + zero. Common unit suffixes of 'k', 'm', or 'g' are supported. + Note that if the number of kept packs is more than gc.autoPackLimit, this configuration variable is ignored, all packs except the base pack diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index a65c9aa62d..fef382a70f 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -77,9 +77,10 @@ be performed as well. instance running on this repository. --keep-largest-pack:: - All packs except the largest pack and those marked with a - `.keep` files are consolidated into a single pack. When this - option is used, `gc.bigPackThreshold` is ignored. + All packs except the largest non-cruft pack, any packs marked + with a `.keep` file, and any cruft pack(s) are consolidated into + a single pack. When this option is used, `gc.bigPackThreshold` + is ignored. AGGRESSIVE ---------- diff --git a/builtin/gc.c b/builtin/gc.c index edd98d35a5..53ef137e1d 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -219,7 +219,7 @@ static struct packed_git *find_base_packs(struct string_list *packs, struct packed_git *p, *base = NULL; for (p = get_all_packs(the_repository); p; p = p->next) { - if (!p->pack_local) + if (!p->pack_local || p->is_cruft) continue; if (limit) { if (p->pack_size >= limit) diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index d9acb63951..df6f2e6e52 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -298,6 +298,49 @@ test_expect_success 'feature.experimental=false avoids cruft packs by default' ' ) ' +test_expect_success '--keep-largest-pack ignores cruft packs' ' + test_when_finished "rm -fr repo" && + git init repo && + ( + cd repo && + + # Generate a pack for reachable objects (of which there + # are 3), and one for unreachable objects (of which + # there are 6). + prepare_cruft_history && + git gc --cruft && + + mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" && + sz="$(test_file_size "${mtimes%.mtimes}.pack")" && + + # Ensure that the cruft pack gets removed (due to + # `--prune=now`) despite it being the largest pack. + git -c gc.bigPackThreshold=$sz gc --cruft --prune=now && + + assert_no_cruft_packs + ) +' + +test_expect_success 'gc.bigPackThreshold ignores cruft packs' ' + test_when_finished "rm -fr repo" && + git init repo && + ( + cd repo && + + # Generate a pack for reachable objects (of which there + # are 3), and one for unreachable objects (of which + # there are 6). + prepare_cruft_history && + git gc --cruft && + + # Ensure that the cruft pack gets removed (due to + # `--prune=now`) despite it being the largest pack. + git gc --cruft --prune=now --keep-largest-pack && + + assert_no_cruft_packs + ) +' + run_and_wait_for_auto_gc () { # We read stdout from gc for the side effect of waiting until the # background gc process exits, closing its fd 9. Furthermore, the From b934207a223a846e98c693c4c6a9ca32bf995688 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:41 -0400 Subject: [PATCH 04/10] t/t5304-prune.sh: prepare for `gc --cruft` by default Many of the tests in t5304 run `git gc`, and rely on its behavior that unreachable-but-recent objects are written out loose. This is sensible, since t5304 deals specifically with this kind of pruning. If left unattended, however, this test would break when the default behavior of a bare "git gc" is adjusted to generate a cruft pack by default. Ensure that these tests continue to work as-is (and continue to provide coverage of loose object pruning) by passing `--no-cruft` explicitly. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- t/t5304-prune.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index 5500dd0842..662ae9b152 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -62,11 +62,11 @@ test_expect_success 'prune --expire' ' test_expect_success 'gc: implicit prune --expire' ' add_blob && test-tool chmtime =-$((2*$week-30)) $BLOB_FILE && - git gc && + git gc --no-cruft && verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE && test-tool chmtime =-$((2*$week+1)) $BLOB_FILE && - git gc && + git gc --no-cruft && verbose test $before = $(git count-objects | sed "s/ .*//") && test_path_is_missing $BLOB_FILE ' @@ -86,7 +86,7 @@ test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' ' test_expect_success 'gc: start with ok gc.pruneExpire' ' git config gc.pruneExpire 2.days.ago && - git gc + git gc --no-cruft ' test_expect_success 'prune: prune nonsense parameters' ' @@ -137,44 +137,44 @@ test_expect_success 'gc --no-prune' ' add_blob && test-tool chmtime =-$((5001*$day)) $BLOB_FILE && git config gc.pruneExpire 2.days.ago && - git gc --no-prune && + git gc --no-prune --no-cruft && verbose test 1 = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE ' test_expect_success 'gc respects gc.pruneExpire' ' git config gc.pruneExpire 5002.days.ago && - git gc && + git gc --no-cruft && test_path_is_file $BLOB_FILE && git config gc.pruneExpire 5000.days.ago && - git gc && + git gc --no-cruft && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc --prune=' ' add_blob && test-tool chmtime =-$((5001*$day)) $BLOB_FILE && - git gc --prune=5002.days.ago && + git gc --prune=5002.days.ago --no-cruft && test_path_is_file $BLOB_FILE && - git gc --prune=5000.days.ago && + git gc --prune=5000.days.ago --no-cruft && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc --prune=never' ' add_blob && - git gc --prune=never && + git gc --prune=never --no-cruft && test_path_is_file $BLOB_FILE && - git gc --prune=now && + git gc --prune=now --no-cruft && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc respects gc.pruneExpire=never' ' git config gc.pruneExpire never && add_blob && - git gc && + git gc --no-cruft && test_path_is_file $BLOB_FILE && git config gc.pruneExpire now && - git gc && + git gc --no-cruft && test_path_is_missing $BLOB_FILE ' @@ -194,7 +194,7 @@ test_expect_success 'gc: prune old objects after local clone' ' cd aclone && verbose test 1 = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE && - git gc --prune && + git gc --prune --no-cruft && verbose test 0 = $(git count-objects | sed "s/ .*//") && test_path_is_missing $BLOB_FILE ) @@ -237,7 +237,7 @@ test_expect_success 'clean pack garbage with gc' ' >.git/objects/pack/fake2.keep && >.git/objects/pack/fake2.idx && >.git/objects/pack/fake3.keep && - git gc && + git gc --no-cruft && git count-objects -v 2>stderr && grep "^warning:" stderr | sort >actual && cat >expected <<\EOF && From b31d45b8315adc49b729496f3c0ed18a41ca08f6 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:43 -0400 Subject: [PATCH 05/10] t/t6501-freshen-objects.sh: prepare for `gc --cruft` by default In a similar spirit as previous commits, prepare for `gc --cruft` becoming the default by ensuring that the tests in t6501 explicitly cover the case of freshening loose objects not using cruft packs. We could run this test twice, once with `--cruft` and once with `--no-cruft`, but doing so is unnecessary, since we already test object rescuing, freshening, and dealing with corrupt parts of the unreachable object graph extensively via t5329. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- t/t6501-freshen-objects.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh index 3968b47ed5..dbfa8a4d4c 100755 --- a/t/t6501-freshen-objects.sh +++ b/t/t6501-freshen-objects.sh @@ -101,7 +101,7 @@ do ' test_expect_success "simultaneous gc ($title)" ' - git gc --prune=12.hours.ago + git gc --no-cruft --prune=12.hours.ago ' test_expect_success "finish writing out commit ($title)" ' @@ -131,7 +131,7 @@ do ' test_expect_success "simultaneous gc ($title)" ' - git gc --prune=12.hours.ago + git gc --no-cruft --prune=12.hours.ago ' # tree should have been refreshed by write-tree @@ -151,7 +151,7 @@ test_expect_success 'do not complain about existing broken links (commit)' ' some message EOF commit=$(git hash-object -t commit -w broken-commit) && - git gc -q 2>stderr && + git gc --no-cruft -q 2>stderr && verbose git cat-file -e $commit && test_must_be_empty stderr ' @@ -161,7 +161,7 @@ test_expect_success 'do not complain about existing broken links (tree)' ' 100644 blob $(test_oid 003) foo EOF tree=$(git mktree --missing stderr && + git gc --no-cruft -q 2>stderr && git cat-file -e $tree && test_must_be_empty stderr ' @@ -176,7 +176,7 @@ test_expect_success 'do not complain about existing broken links (tag)' ' this is a broken tag EOF tag=$(git hash-object -t tag -w broken-tag) && - git gc -q 2>stderr && + git gc --no-cruft -q 2>stderr && git cat-file -e $tag && test_must_be_empty stderr ' From 50685e0e0ba743892c9832c414494093ae3e8703 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:46 -0400 Subject: [PATCH 06/10] t/t6500-gc.sh: refactor cruft pack tests In 12253ab6d0 (gc: add tests for --cruft and friends, 2022-10-26), we added a handful of tests to t6500 to ensure that `git gc` respected the value of `--cruft` and `gc.cruftPacks`. Then, in c695592850 (config: let feature.experimental imply gc.cruftPacks=true, 2022-10-26), another set of similar tests was added to ensure that `feature.experimental` correctly implied enabling cruft pack generation (or not). These tests are similar and could be consolidated. Do so in this patch to prepare for expanding the set of command-line invocations that enable or disable writing cruft packs. This makes it possible to easily test more combinations of arguments without being overly repetitive. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- t/t6500-gc.sh | 114 +++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 76 deletions(-) diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index df6f2e6e52..a2f988c5c2 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -210,93 +210,55 @@ prepare_cruft_history () { git reset HEAD^^ } -assert_cruft_packs () { - find .git/objects/pack -name "*.mtimes" >mtimes && - sed -e 's/\.mtimes$/\.pack/g' mtimes >packs && - - test_file_not_empty packs && - while read pack - do - test_path_is_file "$pack" || return 1 - done mtimes && test_must_be_empty mtimes } -test_expect_success 'gc --cruft generates a cruft pack' ' - test_when_finished "rm -fr crufts" && - git init crufts && - ( - cd crufts && +for argv in \ + "gc --cruft" \ + "-c gc.cruftPacks=true gc" \ + "-c feature.experimental=true gc" \ + "-c gc.cruftPacks=true -c feature.experimental=false gc" +do + test_expect_success "git $argv generates a cruft pack" ' + test_when_finished "rm -fr repo" && + git init repo && + ( + cd repo && - prepare_cruft_history && - git gc --cruft && - assert_cruft_packs - ) -' + prepare_cruft_history && + git $argv && -test_expect_success 'gc.cruftPacks=true generates a cruft pack' ' - test_when_finished "rm -fr crufts" && - git init crufts && - ( - cd crufts && + find .git/objects/pack -name "*.mtimes" >mtimes && + sed -e 's/\.mtimes$/\.pack/g' mtimes >packs && - prepare_cruft_history && - git -c gc.cruftPacks=true gc && - assert_cruft_packs - ) -' + test_file_not_empty packs && + while read pack + do + test_path_is_file "$pack" || return 1 + done Date: Tue, 18 Apr 2023 16:40:49 -0400 Subject: [PATCH 07/10] t/t6500-gc.sh: add additional test cases In the last commit, we refactored some of the tests in t6500 to make clearer when cruft packs will and won't be generated by `git gc`. Add the remaining cases not covered by the previous patch into this one, which enumerates all possible combinations of arguments that will produce (or not produce) a cruft pack. This prepares us for a future commit which will change the default value of `gc.cruftPacks` by ensuring that we understand which invocations do and do not change as a result. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- t/t6500-gc.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index a2f988c5c2..3ba2ae5140 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -218,6 +218,7 @@ assert_no_cruft_packs () { for argv in \ "gc --cruft" \ "-c gc.cruftPacks=true gc" \ + "-c gc.cruftPacks=false gc --cruft" \ "-c feature.experimental=true gc" \ "-c gc.cruftPacks=true -c feature.experimental=false gc" do @@ -243,6 +244,9 @@ do done for argv in \ + "gc" \ + "-c gc.cruftPacks=false gc" \ + "-c gc.cruftPacks=true gc --no-cruft" \ "-c feature.expiremental=true -c gc.cruftPacks=false gc" \ "-c feature.experimental=false gc" do From c58100ab5d33e12c790b89dafee9fd1efbc46a99 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:40:52 -0400 Subject: [PATCH 08/10] t/t9300-fast-import.sh: prepare for `gc --cruft` by default In a similar fashion as previous commits, adjust the fast-import tests to prepare for "git gc" generating a cruft pack by default. This adjustment is slightly different, however. Instead of relying on us writing out the objects loose, and then calling `git prune` to remove them, t9300 needs to be prepared to drop objects that would be moved into cruft packs. To do this, we can combine the `git gc` invocation with `git prune` into one `git gc --prune`, which handles pruning both loose objects, and objects that would otherwise be written to a cruft pack. Likely this pattern of "git gc && git prune" started all the way back in 03db4525d3 (Support gitlinks in fast-import., 2008-07-19), which happened after deprecating `git gc --prune` in 9e7d501990 (builtin-gc.c: deprecate --prune, it now really has no effect, 2008-05-09). After `--prune` was un-deprecated in 58e9d9d472 (gc: make --prune useful again by accepting an optional parameter, 2009-02-14), this script got a handful of new "git gc && git prune" instances via via 4cedb78cb5 (fast-import: add input format tests, 2011-08-11). These could have been `git gc --prune`, but weren't (likely taking after 03db4525d3). Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- t/t9300-fast-import.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index aa55b41b9a..ac237a1f90 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -388,9 +388,7 @@ test_expect_success 'B: accept branch name "TEMP_TAG"' ' INPUT_END - test_when_finished "rm -f .git/TEMP_TAG - git gc - git prune" && + test_when_finished "rm -f .git/TEMP_TAG && git gc --prune=now" && git fast-import Date: Tue, 18 Apr 2023 16:40:57 -0400 Subject: [PATCH 09/10] builtin/gc.c: make `gc.cruftPacks` enabled by default Back in 5b92477f89 (builtin/gc.c: conditionally avoid pruning objects via loose, 2022-05-20), `git gc` learned the `--cruft` option and `gc.cruftPacks` configuration to opt-in to writing cruft packs when collecting or pruning unreachable objects. Cruft packs were introduced with the merge in a50036da1a (Merge branch 'tb/cruft-packs', 2022-06-03). They address the problem of "loose object explosions", where Git will write out many individual loose objects when there is a large number of unreachable objects that have not yet aged past `--prune=`. Instead of keeping track of those unreachable yet recent objects via their loose object file's mtime, cruft packs collect all unreachable objects into a single pack with a corresponding `*.mtimes` file that acts as a table to store the mtimes of all unreachable objects. This prevents the need to store unreachable objects as loose as they age out of the repository, and avoids the problem of loose object explosions. Beyond avoiding loose object explosions, cruft packs also act as a more efficient mechanism to store unreachable objects as they age out of a repository. This is because pairs of similar unreachable objects serve as delta bases for one another. In 5b92477f89, the feature was introduced as experimental. Since then, GitHub has been running these patches in every repository generating hundreds of millions of cruft packs along the way. The feature is battle-tested, and avoids many pathological cases such as above. Users who either run `git gc` manually, or via `git maintenance` can benefit from having cruft packs. As such, enable cruft pack generation to take place by default (by making `gc.cruftPacks` have the default of "true" rather than "false). Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- Documentation/config/feature.txt | 3 --- Documentation/config/gc.txt | 2 +- Documentation/git-gc.txt | 5 +++-- Documentation/gitformat-pack.txt | 4 ++-- builtin/gc.c | 6 +----- t/t6500-gc.sh | 12 ++++-------- 6 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt index e52bc6b858..17b4d39f89 100644 --- a/Documentation/config/feature.txt +++ b/Documentation/config/feature.txt @@ -14,9 +14,6 @@ feature.experimental:: + * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by skipping more commits at a time, reducing the number of round trips. -+ -* `gc.cruftPacks=true` reduces disk space used by unreachable objects during -garbage collection, preventing loose object explosions. feature.manyFiles:: Enable config options that optimize for repos with many files in the diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt index 8d5353e9e0..7f95c866e1 100644 --- a/Documentation/config/gc.txt +++ b/Documentation/config/gc.txt @@ -84,7 +84,7 @@ gc.packRefs:: gc.cruftPacks:: Store unreachable objects in a cruft pack (see linkgit:git-repack[1]) instead of as loose objects. The default - is `false`. + is `true`. gc.pruneExpire:: When 'git gc' is run, it will call 'prune --expire 2.weeks.ago' diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index fef382a70f..90806fd26a 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -54,9 +54,10 @@ other housekeeping tasks (e.g. rerere, working trees, reflog...) will be performed as well. ---cruft:: +--[no-]cruft:: When expiring unreachable objects, pack them separately into a - cruft pack instead of storing them as loose objects. + cruft pack instead of storing them as loose objects. `--cruft` + is on by default. --prune=:: Prune loose objects older than date (default is 2 weeks ago, diff --git a/Documentation/gitformat-pack.txt b/Documentation/gitformat-pack.txt index e06af02f21..0c1be2dbe8 100644 --- a/Documentation/gitformat-pack.txt +++ b/Documentation/gitformat-pack.txt @@ -611,8 +611,8 @@ result of repeatedly resetting the objects' mtimes to the present time. If you are GC-ing repositories in a mixed version environment, consider omitting the `--cruft` option when using linkgit:git-repack[1] and linkgit:git-gc[1], and -leaving the `gc.cruftPacks` configuration unset until all writers understand -cruft packs. +setting the `gc.cruftPacks` configuration to "false" until all writers +understand cruft packs. === Alternatives diff --git a/builtin/gc.c b/builtin/gc.c index 53ef137e1d..ece01e966f 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -48,7 +48,7 @@ static const char * const builtin_gc_usage[] = { static int pack_refs = 1; static int prune_reflogs = 1; -static int cruft_packs = -1; +static int cruft_packs = 1; static int aggressive_depth = 50; static int aggressive_window = 250; static int gc_auto_threshold = 6700; @@ -608,10 +608,6 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (prune_expire && parse_expiry_date(prune_expire, &dummy)) die(_("failed to parse prune expiry value %s"), prune_expire); - prepare_repo_settings(the_repository); - if (cruft_packs < 0) - cruft_packs = the_repository->settings.gc_cruft_packs; - if (aggressive) { strvec_push(&repack, "-f"); if (aggressive_depth > 0) diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index 3ba2ae5140..69509d0c11 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -216,11 +216,9 @@ assert_no_cruft_packs () { } for argv in \ - "gc --cruft" \ + "gc" \ "-c gc.cruftPacks=true gc" \ - "-c gc.cruftPacks=false gc --cruft" \ - "-c feature.experimental=true gc" \ - "-c gc.cruftPacks=true -c feature.experimental=false gc" + "-c gc.cruftPacks=false gc --cruft" do test_expect_success "git $argv generates a cruft pack" ' test_when_finished "rm -fr repo" && @@ -244,11 +242,9 @@ do done for argv in \ - "gc" \ + "gc --no-cruft" \ "-c gc.cruftPacks=false gc" \ - "-c gc.cruftPacks=true gc --no-cruft" \ - "-c feature.expiremental=true -c gc.cruftPacks=false gc" \ - "-c feature.experimental=false gc" + "-c gc.cruftPacks=true gc --no-cruft" do test_expect_success "git $argv does not generate a cruft pack" ' test_when_finished "rm -fr repo" && From 029a632c35861b3395c71e767d80bbf463dc1ae1 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 18 Apr 2023 16:41:00 -0400 Subject: [PATCH 10/10] repository.h: drop unused `gc_cruft_packs` As of the previous commit, all callers that need to read the value of `gc.cruftPacks` do so outside without using the `repo_settings` struct, making its `gc_cruft_packs` unused. Drop it accordingly. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- repo-settings.c | 4 +--- repository.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/repo-settings.c b/repo-settings.c index 0a6c0b381f..a8d0b98794 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -41,10 +41,8 @@ void prepare_repo_settings(struct repository *r) repo_cfg_bool(r, "feature.experimental", &experimental, 0); /* Defaults modified by feature.* */ - if (experimental) { + if (experimental) r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING; - r->settings.gc_cruft_packs = 1; - } if (manyfiles) { r->settings.index_version = 4; r->settings.index_skip_hash = 1; diff --git a/repository.h b/repository.h index 15a8afc5fb..50eb0ce391 100644 --- a/repository.h +++ b/repository.h @@ -33,7 +33,6 @@ struct repo_settings { int commit_graph_generation_version; int commit_graph_read_changed_paths; int gc_write_commit_graph; - int gc_cruft_packs; int fetch_write_commit_graph; int command_requires_full_index; int sparse_index;