Skip to content

Checkpoints time out on large untracked files and leave hundreds of MB of junk in .git/objects every turn #18868

Closed as not planned

Description

@SunkenInTime

What happens

If a project has a large untracked file (a few hundred MB or more), every turn's checkpoint times out after 30 s. Git is killed partway through writing the file into .git/objects, and the partly written file stays there. The next turn does the same thing again.

In one real project, untracked JSON files of 2.1 to 2.8 GB left 132 tmp_obj_* files totalling 22.65 GB in .git/objects.

Reproduction (Windows, Git 2.55, current main)

One untracked 2.6 GiB JSON file in a scratch repo, captured with GitVcsDriver.captureCheckpoint:

Capture Time Result Junk in .git/objects
1 30.9 s timeout 194.0 MiB
2 30.9 s timeout 382.1 MiB
3 30.9 s timeout 571.5 MiB

With no time limit, git add takes 107.8 s. It still takes 80.3 s when the file is already stored, because the checkpoint's private index doesn't keep file stats, so git rereads the whole file on every capture.

Over a full simulated turn, the baseline checkpoint waits 30 s, fails, leaves 182.5 MiB behind, and only then does the provider start.

Cause

VcsProcess stops git after 30 s. Files over core.bigFileThreshold (512 MiB) are streamed into a pack, so stopping git leaves a partial tmp_pack_* (or tmp_obj_*) file behind. Nothing ever removes it.

Possible fix

Leave untracked files over 10 MiB that aren't in HEAD out of the checkpoint, and have restore leave those files alone so it never deletes or overwrites them. Codex's old ghost snapshots used the same 10 MiB limit.

A prototype exists locally. With it:

  • Capture takes 0.6 s and leaves no junk.
  • Restore keeps the 2.6 GiB file unchanged and still reverts the small files.
  • Each capture costs an extra 0.1 s on a clean clone and 0.4 s with 2,764 untracked files (medians of 15 runs).

Open questions

  • How should users find out that a file was left out? Restore won't roll it back, so they need to know. One option: store the skipped paths on the checkpoint and show a note on the turn when the set of skipped files changes.
  • Should T3 remove junk that has already leaked, for example by deleting tmp_obj_* and tmp_pack_* files older than a day?
  • If a file grows past 10 MiB during a turn, it shows up in that turn's diff as deleted, and restore doesn't roll it back.

Workaround

Close T3, then delete the tmp_obj_* files under .git/objects and the tmp_pack_* files under .git/objects/pack. Nothing references them.

Activity

  1. juliusmarminge commented on Oct 13, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Thanks for the detailed measurements. This is the same problem as #3646 (a large untracked file makes git add hit the 30 s checkpoint timeout and leaves tmp_pack_*/tmp_obj_* files behind), and it's already being worked on:

    Closing this as a duplicate so the work stays in one place. Your Windows numbers and the case for a 10 MiB cap would be really useful in #18617. Your workaround (close T3, then delete the tmp_obj_* and tmp_pack_* files) is the right one until those land.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions