On Mon, Jul 16, 2018 at 01:21:40PM -0700, Elijah Newren wrote: > > My understanding is that exploding the objects is intentional behavior, > > to avoid a race where objects are newly referenced while they are being > > pruned. > > > > I am not a fan of that behavior. It's still racy. But when we've > > brought it up in the past, the consensus seems to have been that it's > > better than nothing. Documentation/technical/hash-function-transition.txt > > section "Loose objects and unreachable objects" describes a way to > > eliminate the race. > > Ah, that's good to know and at least makes sense. It seems somewhat > odd, though; loose objects that are two weeks old are just as > susceptible to being referenced anew by new commits, so the default of > running 'git prune --expire=2.weeks.ago' as gc currently does would > also be unsafe, wouldn't it? Why is that any more or less unsafe than > pruning objects only referenced by reflog entries that are more than > 90 days old? The 2-week safety isn't primarily about things which just became unreferenced. It's about things which are in the act of being referenced. Imagine a "git commit" racing with a "git prune". The commit has to create an object, and then it will update a ref to point to it. But between those two actions, prune may racily delete the object! The mtime grace period is what makes that work. Using 2 weeks is sort of ridiculous for that. But it also helps with manual recovery (e.g., imagine a blob added to the index but never committed; 3 days later you may want to try to recover your old work). And you're correct that a new git-commit may still reference an old object (e.g., a blob that's 5 seconds shy of being 2 weeks old that you're including in a new commit). That's why we retain non-fresh objects that are referenced from fresh ones (so as long as you made the new commit recently, it transitively infers freshness on the old blob), and why we fresh mtimes when we elide a write for an existing object. That's _still_ not race-proof, because none of these operations is atomic. git-prune can decide the blob is unfresh at the exact moment you're creating the commit object. -Peff