Skip to content
masterclass Buddy

Git · Command

git fsck

git fsck checks a repository's object database for integrity. It confirms that objects are valid and that everything they refer to is present, then reports corruption, missing objects and objects that nothing points to.

Last updated

How it works

fsck starts from a set of head objects and walks every commit, tree, tag and blob that can be reached from them. Unless you name objects, the heads are the index, every ref and every reflog. Along the way it checks each object's hash and format. It reports missing or bad objects, plus dangling ones: objects that exist but that no other object points to. By default it also checks the refs database. Message IDs such as missingEmail can be configured to change how severe a problem is treated, and a skip list can exempt known-bad objects. The fsck.* settings apply only to this command.

Syntax

git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs] [--[no-]full] [--strict] [--verbose] [--lost-found] [--[no-]dangling] [--[no-]progress] [--connectivity-only] [--[no-]name-objects] [--[no-]references] [<object>…]

Parameters

NameTypeDescription
<object>object nameAn object to use as a head (starting point) for the reachability check. If none is given, fsck uses the index, all refs and all reflogs.
--unreachableflagList objects that exist but cannot be reached from any of the heads.
--[no-]danglingflagShow (default) or hide objects that exist but that no other object points to directly.
--rootflagReport root nodes.
--tagsflagReport tags.
--cacheflagAlso use every object recorded in the index as a head.
--no-reflogsflagDo not count commits as reachable if only a reflog entry refers to them.
--[no-]fullflagAlso check alternate object stores and packfiles. This is on by default.
--connectivity-onlyflagCheck only that reachable objects are present. Blob contents are never read, which makes the check faster.
--strictflagUse stricter checks, for example flagging file modes with the group-write bit set, which older versions of Git created.
--verboseflagPrint more detailed output.
--lost-foundflagSave dangling objects under .git/lost-found/commit/ or .git/lost-found/other/.

Key points

  • With no object arguments, fsck starts its walk from the index, every ref and every reflog. This is why commits you can still reach through the reflog are not reported.
  • Alternate object stores and packfiles are checked by default. Use --no-full to check only the main object directory.
  • --lost-found saves dangling objects so you can get them back. Blobs are written out as file contents, and other objects are saved under their object IDs.
  • fsck also checks the refs database by running git refs verify. Use --no-references to skip this step.
  • If the commit-graph feature is turned on, fsck also verifies the commit-graph file.
  • Each message ID can be set to error, warn or ignore in config. For example, fsck.missingEmail=ignore hides that problem. Messages marked FATAL cannot be changed.
  • A hash mismatch means an object's contents do not match its ID. This is real corruption, not harmless leftover data.
  • fsck cannot repair a corrupt object. You have to get a good copy from a backup or from another clone.

Common mistakes

  • --connectivity-only is faster but only checks that blobs exist. It never reads their contents, so a damaged file in history goes unnoticed.
  • The receive.fsck.* and fetch.fsck.* settings do not fall back to fsck.*. To get the same behaviour everywhere, you must set all three.
  • fsck.skipList only silences objects with non-fatal problems. It cannot hide objects that are actually corrupt.
  • A misspelled fsck.<msg-id> setting stops fsck completely. The same mistake in receive or fetch settings only produces a warning.

Example: Find and save a commit lost after a hard reset

#!/usr/bin/env bash
set -euo pipefail
repo=$(mktemp -d)
cd "$repo"
git init -q
git commit -q --allow-empty -m "first"
git commit -q --allow-empty -m "second"

# Drop "second" from the branch; only the reflog still refers to it
git reset -q --hard HEAD~1

# Ignore reflogs so the dropped commit is reported as dangling
git fsck --no-reflogs

# Save dangling objects under .git/lost-found
git fsck --no-reflogs --lost-found
ls .git/lost-found/commit/

# Fast health check without the dangling-object list
git fsck --connectivity-only --no-dangling && echo "connectivity OK"

The script drops a commit from its branch, runs fsck with --no-reflogs so the commit shows up as dangling, saves it with --lost-found, and then runs a quick connectivity check.

When to use it

Recovering deleted work

A branch was deleted together with its reflog. Running fsck lists the dangling commits that still exist, so you can find the right one and point a new branch at it.

Diagnosing a suspect repository

After a disk failure or a crash during a write, run git fsck --full --no-dangling to list only real problems, such as missing or broken objects.

Accepting a legacy project

An old repository has early commits with bad committer emails. List those object IDs in fsck.skipList, and set receive.fsck.skipList and fetch.fsck.skipList too, so fsck checks pass without hiding new problems of the same kind.

Interview questions

QWhat is the difference between a dangling object and an unreachable object in git fsck output?

An unreachable object cannot be reached, directly or indirectly, from any head. A dangling object exists but no other object points to it directly. fsck lists dangling objects by default, while unreachable objects appear only with --unreachable.

Follow-up: Why can't fsck see a commit that only the reflog points to? Because reflogs are included in the default heads, so that commit counts as reachable. Pass --no-reflogs to have it reported.

QHow would you speed up fsck on a very large repository, and what do you give up?

Use --connectivity-only, which skips reading blobs and only checks that every referenced object exists. Add --no-dangling as well, so fsck doesn't have to walk unreachable history to find dangling tips. The cost is that corrupted blobs and format errors are not detected.

Follow-up: Does it still catch a missing blob? Yes. It confirms that referenced blobs exist; it just doesn't read their contents.

QAn old repository fails fsck with missingEmail errors in a few early commits. How do you handle that properly?

The best approach is to list the specific bad object IDs in fsck.skipList. Setting fsck.missingEmail=ignore would also let new commits with the same problem pass unnoticed.

Follow-up: Why do pushes to the server still fail after that change? Because receive.fsck.skipList doesn't fall back to fsck.skipList, so it has to be set on the server separately.

  • git gc
  • git prune
  • git reflog
  • git refs
  • git commit-graph
  • git rev-parse
  • git config
  • git fsck-objects

Source: Git - git-fsck Documentation. Checked 2026-11-02.