Re: [PATCH] repack: do not rebuild packs on --dry-run
- From
D. Ben Knoble <ben.knoble@gmail.com>
- Date
- Oct 8, 2026, 12:56 UTC
- Message-ID
- <CALnO6CD9roPhKsYRVXRuZXQckTmbCskKmvxiUyxp6vkJ03S8rQ@mail.gmail.com>
- In-Reply-To
- <20261008062521.25505-1-r.siddharth.shrimali@gmail.com>
Hi Siddharth,
On Thu, Oct 8, 2026 at 2:25 AM Siddharth Shrimali <r.siddharth.shrimali@gmail.com> wrote:
Show 17 quoted lines
> > "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 command > still exits successfully, so the user is not told that the repository > was modified. > > The existing guard only skips the implied "delete_redundant = 1", so > it does not stop an explicit -d, nor the new pack from being written. > > 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
Show 18 quoted lines
> Reported-by: Coy Geek <coygeek@gmail.com>
> Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
> ---
> Bug report:
> https://lore.kernel.org/git/CACgTecOm+=vbf50tZNXhcYvRi1ZTsQwbjVoJAbQqs2CmXdJCxg@mail.gmail.com/
>
> builtin/repack.c | 8 ++++++++
> t/t7706-repack-drop-filtered.sh | 19 +++++++++++++++++++
> 2 files changed, 27 insertions(+)
>
> diff --git a/builtin/repack.c b/builtin/repack.c
> index c4360382c1..c048053912 100644
> --- a/builtin/repack.c
> +++ b/builtin/repack.c
> @@ -391,6 +391,14 @@ int cmd_repack(int argc,
> oidset_iter_init(&drop_oids, &iter);
> while ((oid = oidset_iter_next(&iter)))
> printf("%s\n", oid_to_hex(oid));Just outside the patch context is the "if (dry_run)" conditional, so this is the right place. (In this case, formatting with a larger "-U" value might help.)
Show 6 quoted lines
> + > + /* > + * add an exit here, so that dry run does not > + * go on to rebuild any pack or delete anything, even > + * if the user explicitly asked for -d > + */
2 notes:
1. "add an exit" will stop making sense as soon as the patch becomes a commit; that is, it only makes sense in the context of proposed changes. Once those changes are part of the code base, the comment and code are not adding anything. They simply are. So, if we need a comment (see 2), it might be best phrased as "exit here so that […]", keeping some of your original wording. Or we could be more terse: "skip non-dry-run operations" or something. 2. Do we need such a comment, I wonder? git-blame will point folks towards this commit :)
> + ret = 0; > + goto cleanup;
This matches the pattern elsewhere in this procedure, so that looks good.
Show 35 quoted lines
> } > } > > 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 > @@ -135,6 +135,25 @@ test_expect_success '--dry-run does not remove the filtered objects' ' > 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) && > -- > 2.56.0
Thanks for adding a test to cover this. It looks reasonable to me, but I didn't study the surrounding tests to think very critically about it.
-- D. Ben Knoble