Git development
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Cc: git@vger.kernel.org,  coygeek@gmail.com,  ben.knoble@gmail.com,
	 ps@pks.im
Subject: Re: [PATCH v3] repack: do not rebuild packs on --dry-run
Date: Fri, 16 Oct 2026 13:47:53 -0700	[thread overview]
Message-ID: <xmqqse25e5ja.fsf@gitster.g> (raw)
In-Reply-To: <20261016191344.82688-1-r.siddharth.shrimali@gmail.com> (Siddharth Shrimali's message of "Sat, 17 Oct 2026 00:43:44 +0530")

Siddharth Shrimali <r.siddharth.shrimali@gmail.com> writes:

> "git repack --drop-filtered --dry-run" is documented to list the
> objects that would be dropped "without rebuilding any pack or
> deleting anything", but it does both.
>
> This is a bug in cmd_repack(): after printing the candidates, the
> --dry-run block falls through into the regular repack code.
> repack_promisor_objects() writes a new promisor pack, and with -d,
> existing_packs_remove_redundant() deletes the old packs.
>
> The existing guard only skips the implied "delete_redundant = 1", so
> it does not stop an explicit -d, and it does not stop the new pack
> from being written either.
>
> This has been broken since --dry-run was introduced in 1e746b00aa
> (builtin/repack: add --drop-filtered and --dry-run options). The
> --dry-run block never returned early, so a dry run has always gone
> on to do a regular repack. It was not broken by a later change.

As a part of an answer to a question "was this broken from the
beginning, or is it a regression?", the last sentence may have
value, but as part of a standalone proposed log message, it sounds
weird, don't you think?  You already clearly said this was broken
since the beginning.

> Fix it by returning right after the candidates are listed, and add a
> test that checks the pack directory is unchanged with and without -d.

Makes sense.

> A dry run can no longer get past that point, so the two "!dry_run"
> checks that tried to keep it from deleting or dropping anything are
> now redundant.

This makes sense as an explanation on the differences between v2 and
v3, but for those who are reading v3 standalone (which are our
primary target audience, i.e., those who read "git log -p" in the
future), it is on the borderline redundant, as it is a natural part
of what you already described, i.e., return right after giving a
list without doing anything.

Will queue as-is.  I think it is good enough, even though I did
nitpick a couple of points in the above.

Thanks.

> Reported-by: Coy Geek <coygeek@gmail.com>
> Helped-by: D. Ben Knoble <ben.knoble@gmail.com>
> Helped-by: Patrick Steinhardt <ps@pks.im>
> Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
> ---
> Bug report:
> https://lore.kernel.org/git/CACgTecOm+=vbf50tZNXhcYvRi1ZTsQwbjVoJAbQqs2CmXdJCxg@mail.gmail.com/
>
> Changes since v2:
>  - dropped the "!dry_run" checks around the implied -d and the
>    repack_promisor_objects() call, which the early return made
>    redundant

>  builtin/repack.c                | 14 ++++++++++----
>  t/t7706-repack-drop-filtered.sh | 19 +++++++++++++++++++
>  2 files changed, 29 insertions(+), 4 deletions(-)
>
> diff --git a/builtin/repack.c b/builtin/repack.c
> index c4360382c1..19894804f0 100644
> --- a/builtin/repack.c
> +++ b/builtin/repack.c
> @@ -347,18 +347,17 @@ int cmd_repack(int argc,
>  		}
>  
>  		write_bitmaps = 0;
>  
>  		/*
>  		 * Dropping objects means rebuilding the promisor packs
>  		 * without them and then removing the old packs, so the
> -		 * redundant packs must be deleted. Imply -d on a real run.
> +		 * redundant packs must be deleted. Imply -d.
>  		 */
> -		if (!dry_run)
> -			delete_redundant = 1;
> +		delete_redundant = 1;
>  
>  		ret = enumerate_promisor_blobs(repo, &po_args.filter_options, &drop_oids);
>  
>  		if (ret)
>  			goto cleanup;
>  
>  		/*
> @@ -387,14 +386,21 @@ int cmd_repack(int argc,
>  		if (dry_run) {
>  			struct oidset_iter iter;
>  			const struct object_id *oid;
>  
>  			oidset_iter_init(&drop_oids, &iter);
>  			while ((oid = oidset_iter_next(&iter)))
>  				printf("%s\n", oid_to_hex(oid));
> +
> +			/*
> +			 * Only list the candidates to be dropped; skip
> +			 * the actual repack
> +			 */
> +			ret = 0;
> +			goto cleanup;
>  		}
>  	}
>  
>  	if (delete_redundant && repo->repository_format_precious_objects)
>  		die(_("cannot delete packs in a precious-objects repo"));
>  
>  	die_for_incompatible_opt3(unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE), "-A",
> @@ -501,15 +507,15 @@ int cmd_repack(int argc,
>  			strvec_push(&cmd.args, "--write-bitmap-index-quiet");
>  	}
>  	if (use_delta_islands)
>  		strvec_push(&cmd.args, "--delta-islands");
>  
>  	if (pack_everything & ALL_INTO_ONE) {
>  		repack_promisor_objects(repo, &po_args, &names, packtmp,
> -			(drop_filtered && !dry_run) ? &drop_oids : NULL);
> +			drop_filtered ? &drop_oids : NULL);
>  
>  		if (existing_packs_has_non_kept(&existing) &&
>  		    delete_redundant &&
>  		    !(pack_everything & PACK_CRUFT)) {
>  			for_each_string_list_item(item, &names) {
>  				strvec_pushf(&cmd.args, "--keep-pack=%s-%s.pack",
>  					     packtmp_name, item->string);
> diff --git a/t/t7706-repack-drop-filtered.sh b/t/t7706-repack-drop-filtered.sh
> index cb36115834..a1c475e4ec 100755
> --- a/t/t7706-repack-drop-filtered.sh
> +++ b/t/t7706-repack-drop-filtered.sh
> @@ -131,14 +131,33 @@ test_expect_success '--dry-run does not remove the filtered objects' '
>  	git -C repo -c repack.writeBitmaps=false \
>  		repack --drop-filtered --filter=blob:limit=1k --dry-run -a >out &&
>  
>  	# Candidate blob must still be present after a dry run.
>  	git -C repo cat-file -e "$BIG"
>  '
>  
> +test_expect_success '--dry-run leaves the pack directory untouched' '
> +	BIG=$(cat big_oid) &&
> +	packdir=repo/.git/objects/pack &&
> +
> +	for opt in "" -d
> +	do
> +		ls $packdir >before &&
> +
> +		git -C repo -c repack.writeBitmaps=false \
> +			repack --drop-filtered --filter=blob:limit=1k \
> +			--dry-run -a $opt >out &&
> +
> +		ls $packdir >after &&
> +		test_cmp before after &&
> +		test_grep "$BIG" out &&
> +		git -C repo cat-file -e "$BIG" || return 1
> +	done
> +'
> +
>  test_expect_success '--drop-filtered removes the promisor blob locally' '
>  	BIG=$(cat big_oid) &&
>  	SMALL=$(cat small_oid) &&
>  
>  	git -C repo -c repack.writeBitmaps=false \
>  		repack --drop-filtered --filter=blob:limit=1k -a &&

  reply	other threads:[~2026-10-16 20:47 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08  6:25 [PATCH] repack: do not rebuild packs on --dry-run Siddharth Shrimali
2026-10-08 12:56 ` D. Ben Knoble
2026-10-10 19:53   ` Siddharth Shrimali
2026-10-08 14:23 ` Junio C Hamano
2026-10-10 20:05   ` Siddharth Shrimali
2026-10-10 21:00 ` [PATCH v2] " Siddharth Shrimali
2026-10-10 21:06   ` Ben Knoble
2026-10-11  5:57     ` Junio C Hamano
2026-10-13 11:30   ` Patrick Steinhardt
2026-10-16 18:15     ` Siddharth Shrimali
2026-10-16 19:13   ` [PATCH v3] " Siddharth Shrimali
2026-10-16 20:47     ` Junio C Hamano [this message]
2026-10-17  8:23       ` Siddharth Shrimali

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqse25e5ja.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=ben.knoble@gmail.com \
    --cc=coygeek@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=ps@pks.im \
    --cc=r.siddharth.shrimali@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox