When the reflog has no entry for a lost commit, how do you find it with git fsck?
answer
- Ask the object database, not the ref log
- Connectivity check over all objects
- Dangling versus unreachable objects
- --lost-found writes them to a directory
- Reflog entries count as roots by default
basics
~20 sgit fsck walks the whole object database and reports objects nothing points at. Use git fsck --lost-found to write dangling commits into .git/lost-found/commit/, inspect candidates with git show, then re-anchor the right one with git branch.
solid answer
~50 sThe reflog only records movements of refs in *this* repository, so it is blind to commits that arrived some other way — objects fetched but never referenced, a stash entry that was dropped, or history whose reflog entries have already expired. For those I go to `git fsck`, which verifies connectivity across the object database and reports what is unreachable. `git fsck --lost-found` writes each dangling commit into `.git/lost-found/commit/` and other dangling objects into `.git/lost-found/other/`; `git fsck --unreachable` just lists them. By default fsck treats reflog entries as roots, so `--no-reflogs` is what exposes commits that are only kept alive by a reflog. The output is noisy — dangling blobs from ordinary staging are normal — so I inspect candidates with `git show` or `git log --oneline`, then `git branch rescue <hash>` on the real one.
code
console · 8 lines$ git fsck --lost-found --no-reflogs
notice: HEAD points to an unborn branch (main)
Checking object directories: 100% (256/256), done.
dangling commit 4b7de1099e5d1d4d6ff4ee2b5b0b3f0e6a1c9a33
dangling blob 1f2c9a7d8b1e0c3a5f6d2b4e7c8a9d0b1e2f3a4b
$ git show 4b7de10 --stat
$ git branch rescue 4b7de10go deeper
Know that fsck exists as the fallback when the reflog has nothing, and that git fsck --lost-found lists dangling commits you can then check out or branch from.
Explain reachability: fsck walks every object from the roots and reports what nothing points at, which is why dangling blobs from ordinary staging show up as noise alongside the commit you actually want.
Show incident discipline — freeze housekeeping, copy .git before investigating, distinguish dangling from unreachable, and always finish by anchoring the object with a branch or tag rather than leaving it floating.
Speak to the limits: fsck is a last resort whose success depends on the prune window, so the real control is upstream — pushed topic branches, mirrors, and backup policy that make single-clone recovery unnecessary.
## When fsck is the right tool The reflog is the first stop for lost work, but it has real blind spots. It records updates to refs made *in this repository*, so it never sees: commits fetched into the object database that no ref ended up referencing; a stash entry whose reflog slot was dropped; commits whose reflog entries have already expired; or anything created in a repository you are inspecting after the fact. Whenever the reflog comes up empty, the fallback is to ask the object database directly what it is holding. ## What fsck does `git fsck` — file system check — verifies the connectivity and validity of every object in the repository. It walks from the roots (refs, and by default reflog entries and the index) and reports objects it cannot reach, plus any corruption it finds. The recovery-relevant options are: - `--dangling` — report objects that nothing points at. This is on by default; `--no-dangling` silences it. - `--unreachable` — print every object not reachable from any ref, which is a superset of dangling and much noisier. - `--lost-found` — write dangling objects out as files: commits and tags into `.git/lost-found/commit/`, everything else into `.git/lost-found/other/`. For blobs, the *contents* are written rather than the object name, which is what makes staged-but-lost file content readable again. - `--no-reflogs` — stop treating reflog entries as roots. Without it, a commit that is still named by a reflog entry counts as reachable and will not be reported; with it, exactly those commits surface. ## Reading the output Typical output lines look like `dangling commit 4b7de10…` and `dangling blob 1f2c9a…`. Dangling blobs are extremely common and usually harmless: every `git add` you later replaced left one behind. Dangling trees are similar. What you are hunting for is `dangling commit`. Inspect each candidate: - `git show <hash>` — the commit message, author, date, and diff. - `git log --oneline <hash> -5` — the commit and its ancestry, which is usually the fastest way to recognise your own work. - `git cat-file -t <hash>` and `git cat-file -p <hash>` — the plumbing view when you want the raw object. For a stray blob whose filename you no longer know, `git show <blob-hash>` prints its contents, and you decide where it belonged. ## Re-anchoring Finding the object is only half of it: until some ref points at it, the commit is still one garbage collection away from disappearing. Make it reachable: - `git branch rescue-<something> <hash>` for a commit you want to keep working on. - `git tag salvage <hash>` when you just want it pinned while you decide. - `git cherry-pick <hash>` if you only want its change applied to your current branch. ## Practical cautions fsck is a full-database walk. On a large repository it is slow and memory-hungry, so it is not something to run casually in a loop. It also reports objects that are unreachable *for perfectly good reasons* — dropped stashes, abandoned rebases, replaced amends — so a long list is not evidence of a problem. Conversely, `git fsck` finding nothing when you expected a commit usually means garbage collection has already pruned it, and at that point there is no local recovery path: your remaining options are another clone that still has the object, or a filesystem-level backup of `.git`. Before doing anything else in a repository where work is missing, stop running commands that trigger automatic housekeeping, and consider taking a copy of the `.git` directory so that your investigation cannot make things worse. ## How this fits with the reflog The two tools answer different questions. The reflog answers "where has this ref been?" and is cheap, precise, and annotated with the operation that caused each move. fsck answers "what is in this object database that nothing references?" and is exhaustive but unlabelled — no dates of movement, no operation names, just objects. The professional routine is reflog first because it is precise, fsck second because it is complete, and a rescue ref in both cases because an object without a ref is not yet saved.
- Why does git fsck usually report dangling blobs even in a healthy repository?Because git add writes a blob object immediately. Any staged version you later amended, restaged, or discarded leaves that blob behind with nothing pointing at it. The same happens for trees written during aborted operations. They are normal residue, cleared by garbage collection, not a sign of damage.
- What does --no-reflogs change about the result?By default fsck treats reflog entries as roots, so a commit still named in a reflog counts as reachable and is not reported. --no-reflogs drops those roots, which surfaces exactly the commits that used to be on a ref and now survive only through the reflog — useful when you want to see the full set of at-risk objects.
- fsck finds nothing. What is left?If the object is not in the database, garbage collection has already pruned it and there is no local recovery path. The remaining options are another clone or a mirror that still holds the object, or a filesystem or backup copy of the .git directory. This is why you stop touching the repository as soon as you notice loss.
The reflog is the building's visitor log; fsck is a floor-by-floor sweep. The log is faster and tells you who came and went, but only the sweep finds someone nobody signed in.
saying these in an interview costs you the question
- Treats every dangling blob as repository corruption
- Believes fsck can recover objects gc already pruned
- Stops at finding the hash without creating a ref
- Thinks fsck is cheap enough to run routinely on huge repos
- Assumes fsck reports commits that reflog entries still reference