git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 0/6] repack: don't lose objects to a ".keep" that appears mid-run

From
QGqeesung via GitGitGadget <gitgitgadget@gmail.com>
Date
Sep 14, 2026, 11:31 UTC
Message-ID
<pull.2219.git.1789385483.gitgitgadget@gmail.com>

A concurrent push can make "git repack -d" delete a pack whose objects were never copied anywhere, and exit 0. We hit this in production: a ref pointing at a commit that no longer exists, on git 2.43, and it reproduces on master.

What happens:
 * repack scans for ".keep" files and decides which packs to delete, then
   spawns pack-objects with --honor-pack-keep, which scans again;
 * in between, a push of content identical to an earlier one finishes
   migrating its quarantine. Its pack is a duplicate and is dropped, but its
   ".keep" is linked into place, onto the old pack;
 * pack-objects sees that ".keep" and leaves the pack's objects out; repack
   deletes the pack by its earlier list, with force_delete.
Two things are wrong, and each is fixed on its own:
 * 1/6: receive-pack removes a ".keep" it never installed -- the one it
   linked onto somebody else's pack, or a foreign one when its own push was
   rejected before any migration. Only remove a ".keep" that carries our own
   message.
 * 6/6: repack and pack-objects each scan for ".keep" files. Hand
   pack-objects the snapshot repack took at startup instead.
Patches 2-5 are what 6/6 needs to be safe:
 * 2/6: under --stdin-packs=follow, a --keep-pack pack stops the traversal
   like a "^" pack; on-disk ".keep" packs never did.
 * 3/6: the cruft walk goes by a stale kept-pack cache, which
   --honor-pack-keep happened to mask. Pre-existing, reproducible today.
 * 4/6: look --keep-pack names up in a sorted list; it gets long.
 * 5/6: --keep-pack-from-file, since a repository can have more kept packs
   than fit on a command line (32K characters on Windows).

Every fix comes with a test that fails without it; the race itself is reproduced in t7703 by having a ".keep" appear as pack-objects starts. The full suite passes, and the series merges cleanly into next and seen.

Qin ShiCheng (6):
  odb: don't remove a ".keep" we never installed
  pack-objects: keep --keep-pack open when following
  pack-objects: reset kept-pack cache for cruft walk
  pack-objects: sort --keep-pack list for lookup
  pack-objects: add --keep-pack-from-file
  repack: tell pack-objects which packs are kept
 Documentation/git-pack-objects.adoc |  8 +++
 builtin/pack-objects.c              | 71 +++++++++++++++++----
 builtin/repack.c                    | 15 +++++
 object-file.c                       | 95 ++++++++++++++++++++++-------
 odb/source-packed.h                 |  3 +-
 packfile.c                          |  9 ++-
 packfile.h                          |  7 +++
 repack-filtered.c                   |  3 -
 repack.c                            | 34 ++++++++++-
 repack.h                            | 17 +++++-
 t/t5329-pack-objects-cruft.sh       | 40 ++++++++++++
 t/t5331-pack-objects-stdin.sh       | 87 ++++++++++++++++++++++++++
 t/t5547-push-quarantine.sh          | 52 ++++++++++++++++
 t/t7700-repack.sh                   | 43 +++++++++++++
 t/t7703-repack-geometric.sh         | 72 ++++++++++++++++++++++
 tempfile.c                          | 12 ++++
 tempfile.h                          |  9 +++
 17 files changed, 533 insertions(+), 44 deletions(-)
base-commit: 3cb9185f65410273787f74333cc027d2ea5daada
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2219%2Fqeesung%2Frepack-kept-packs-snapshot-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2219/qeesung/repack-kept-packs-snapshot-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2219
-- 
gitgitgadget
Next: Qin ShiCheng via GitGitGadget
Message 1 of 18 in “repack: don't lose objects to a ".keep" that appears mid-run”
  1. 0/6 repack: don't lose objects to a ".keep" that appears mid-runqeesung via GitGitGadget, Sep 14, 2026
  2. 1/6 odb: don't remove a ".keep" we never installedQin ShiCheng via GitGitGadget, Sep 14, 2026
  3. Justin ToblerSep 15, 2026
  4. Qin ShiChengSep 16, 2026
  5. 2/6 pack-objects: keep --keep-pack open when followingQin ShiCheng via GitGitGadget, Sep 14, 2026
  6. 3/6 pack-objects: reset kept-pack cache for cruft walkQin ShiCheng via GitGitGadget, Sep 14, 2026
  7. 4/6 pack-objects: sort --keep-pack list for lookupQin ShiCheng via GitGitGadget, Sep 14, 2026
  8. 5/6 pack-objects: add --keep-pack-from-fileQin ShiCheng via GitGitGadget, Sep 14, 2026
  9. 6/6 repack: tell pack-objects which packs are keptQin ShiCheng via GitGitGadget, Sep 14, 2026
  10. 0/5 repack: don't lose objects to a ".keep" that appears mid-runqeesung via GitGitGadget, Sep 18, 2026
  11. 1/5 pack-objects: keep --keep-pack open when followingQin ShiCheng via GitGitGadget, Sep 18, 2026
  12. 2/5 pack-objects: reset kept-pack cache for cruft walkQin ShiCheng via GitGitGadget, Sep 18, 2026
  13. Junio C HamanoSep 22, 2026
  14. Qin ShiChengSep 23, 2026
  15. Junio C HamanoSep 23, 2026
  16. 4/5 pack-objects: add --keep-pack-from-fileQin ShiCheng via GitGitGadget, Sep 18, 2026
  17. 3/5 pack-objects: sort --keep-pack list for lookupQin ShiCheng via GitGitGadget, Sep 18, 2026
  18. 5/5 repack: tell pack-objects which packs are keptQin ShiCheng via GitGitGadget, Sep 18, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.