Run git fsck before you have a corruption emergency, not during one. It checks a repository's object database, tells a clean result apart from missing or corrupt objects, and lets you dig into unreachable history without changing anything. Allow about ten minutes for a normal repository, longer for a large object store. The examples use Git 2.43.0 from the installed git-man package version 1:2.43.0-1ubuntu7.3.
You need read access to the repository and its .git directory. Run the checks as the repository owner where possible. git fsck itself does not need sudo, and using elevated privileges can leave root-owned files behind if you later use an option that writes output.
Change to the working tree you mean to examine, then confirm Git actually sees it as a repository:
$ cd /path/to/repository
$ git rev-parse --show-toplevel
/path/to/repository
$ git --version
git version 2.43.0
Swap in a real path. If git rev-parse fails, stop and find the correct working tree or bare repository first, do not point git fsck at a guessed directory and treat the resulting error as evidence of corruption.
Checkpoint: you should have a repository path and a version string in hand before continuing.
With no object names given, git fsck uses the index, refs under refs, and reflogs as its default heads. On Git 2.43.0, full checking is the default, so packed objects and any configured alternate object stores are included too.
$ git fsck
A clean repository normally prints nothing and returns status 0. Capture the status immediately if you are diagnosing a script or automation failure:
$ git fsck
$ status=$?
$ printf 'git fsck status: %s\n' "$status"
git fsck status: 0
Do not mistake silence for a frozen command, on a large repository just wait for it to finish. Progress normally goes to standard error when attached to a terminal; --no-progress suppresses it and --progress forces it even when standard error is redirected elsewhere.
When the database has a problem, the diagnostic names the class of problem plus an object name, and the distinction matters:
missing means another object refers to one that is not present.hash mismatch means the stored content does not match its object name. Treat this as a serious integrity problem.dangling means an object exists but is not directly used. A dangling commit can still be the tip of useful abandoned work.unreachable means the object is not reachable from the heads used for this check. It is not automatically damaged.Save the complete diagnostic before attempting any repair. git fsck cannot recreate a corrupt object, the manual points you to backups or another repository holding the object. Avoid deleting anything just because it looks unusual until you have checked references, reflogs and backups first.
Checkpoint: status 0 with no integrity diagnostics is the ordinary success case. Any missing or hash mismatch line needs investigation before routine maintenance continues.
Use --unreachable when your question is whether objects exist outside the current reference graph:
$ git fsck --unreachable --no-reflogs
unreachable commit 0123456789abcdef0123456789abcdef01234567
That object ID is an example shape, not a value to paste. --no-reflogs drops reflog entries from the heads used for reachability, useful when hunting for commits that used to be referenced but no longer are. Without it, reflog-only commits count as reachable.
For a quieter report, --no-dangling skips the default dangling-object output. To inspect a candidate commit without touching anything, just ask Git to show it:
$ git show --stat --oneline 0123456789abcdef0123456789abcdef01234567
Only restore useful work by creating a new reference or branch after you have reviewed the object and confirmed it belongs to your repository:
$ git branch recovered-work 0123456789abcdef0123456789abcdef01234567
$ git log --oneline -1 recovered-work
This changes repository metadata, so treat it as a deliberate state change. If the branch was created by mistake, undo just that with git branch -D recovered-work after checking the name. Deleting the branch does not immediately repair or delete the underlying object.
--connectivity-only checks that reachable commits, trees and tags refer to objects that exist, while skipping blob contents entirely. It is a good quick connectivity check, but it will not catch corruption inside blob objects or semantic format problems within them.
$ git fsck --connectivity-only --no-dangling
$ printf 'connectivity status: %s\n' "$?"
connectivity status: 0
Reach for the normal full check when object validity matters, not just references. Add --strict when auditing a newer project for legacy format problems, such as an old file mode with the group-write bit set:
$ git fsck --strict --no-dangling
Older repositories can report strict-check findings even when they are perfectly usable. Record the exact messages and decide whether they are known legacy data before changing any objects.
Most of the checks above are read-only. --lost-found is different: it writes dangling objects below .git/lost-found/commit/ or .git/lost-found/other/, and for blobs it writes the actual blob contents, not just the object name.
Warning: do not use this as a routine repair command. It can leave a pile of recovered material scattered through the repository, and it does not reconstruct missing or corrupt objects:
$ git fsck --lost-found --no-reflogs
$ find .git/lost-found -type f -maxdepth 3 -print
Review the files before moving or deleting them. If you need to remove an accidentally created lost-found directory, confirm its exact path and contents first, then remove only that directory through your normal change-control process. Keep a copy if the objects might be evidence or recovery material.
Git can change the severity of named fsck messages with settings such as fsck.missingEmail, and can list known non-fatal object names with fsck.skipList. Neither one cures corrupted objects, a skip list is for established, known exceptions, not a way to hide a new failure.
If a check fails over a message you believe is legacy data, record the object name, message ID and repository history first. Keep fetch and receive settings deliberately aligned: fetch.fsck.* and receive.fsck.* do not automatically fall back to the ordinary fsck.* setting.
git fsck ran in the intended repository as an ordinary user.missing, hash mismatch, dangling and unreachable objects.--connectivity-only was not mistaken for a full content check.--lost-found was treated as a writing operation, not an automatic repair.