Check a Git Repository's Object Database with git-fsck-objects
You will finish with a read-only check of a Git repository's object database, a way to separate unused history from actual corruption, and a quicker check for connectivity when a full scan is too slow. On this machine, git-fsck-objects is provided by Git 2.43.0, package git-man version 1:2.43.0-1ubuntu7.3. Allow ten minutes for a normal repository, or longer if it contains large packs.
The route
Jump straight to the step you need, or tick off Done means at the end.
The command does not need root when you own the repository. It reads Git metadata and may write files only if you explicitly request --lost-found. The examples below avoid that option and do not change commits, refs or working files.
1. Start in the repository you mean to inspect
Change into the working tree or set GIT_DIR for a bare repository. Check the location before running a diagnostic command, especially when a shell script has changed directory earlier:
$ cd /path/to/repository
$ git rev-parse --show-toplevel
/path/to/repository
$ git status --short
The last command should be empty if the worktree is clean, but a dirty worktree does not prevent fsck. This check is about the object database, not about uncommitted files. Do not confuse a repository's working directory with the objects that record its history.
Checkpoint
The path printed by git rev-parse is the repository you intended to examine. If it is wrong, stop and correct the directory before continuing.
2. Run the normal integrity check
git-fsck-objects is an alias for git fsck. The latter is the clearer spelling for new scripts, while the command named in this guide remains useful when an existing tool invokes it. Suppress terminal progress when capturing output:
$ git-fsck-objects --full --no-progress
$ printf 'exit status: %s\n' "$?"
exit status: 0
On a healthy repository, no diagnostic lines and status 0 are a useful result. --full includes the main object directory, packs and configured alternate object pools. Full checking is the default in this Git release, but spelling it out makes the scope visible in a runbook.
The no-argument form uses the index, refs and reflogs as heads. That means an object referenced only by a reflog is normally treated as reachable. This is often what you want during routine maintenance, because recently moved or deleted branch tips may still be recoverable through reflogs.
3. Read the useful diagnostics
Run the same check without hiding its output when you are investigating a report:
$ git fsck --full --no-progress
missing blob 0123456789abcdef0123456789abcdef01234567
error: object missing: 0123456789abcdef0123456789abcdef01234567
The object ID above is an illustrative shape, not a prediction of your repository's output. A missing object is referenced but absent. hash mismatch means the stored contents do not match the object's name. Either is an integrity problem. Do not delete objects to make the report disappear. Find a known-good clone, backup or remote and restore the missing data using a recovery plan appropriate to that repository.
A dangling object exists but is not directly used. A dangling commit can be an old branch tip and may still contain valuable work. unreachable means an object is not reachable from the selected heads. Neither message alone proves corruption or says that deletion is safe.
4. Look for history hidden by reflogs
To search for commits that used to be referenced but remain only in reflogs, exclude reflogs from the reachability roots:
$ git fsck --full --no-reflogs --unreachable --no-progress
unreachable commit 0123456789abcdef0123456789abcdef01234567
The object ID and the number of results vary. Inspect a candidate before deciding whether it matters:
$ git show --stat --oneline 0123456789abcdef0123456789abcdef01234567
Use a complete object name copied from fsck output. If the commit is useful, create a new reference before reflog expiry removes your easy route back to it:
$ git branch recovered-work 0123456789abcdef0123456789abcdef01234567
$ git log -1 --oneline recovered-work
This changes repository state by creating a branch. Confirm the object first and choose a branch name that does not already exist. To undo only this example, remove the new branch after checking it is the one you created:
$ git branch -d recovered-work
Git may refuse -d if the branch is not merged. That refusal protects the reference. Do not replace it with -D unless you have deliberately reviewed the commit and accepted the loss of that branch name.
5. Use a faster connectivity-only check when appropriate
For a large repository, check reachable commits and trees without reading blob contents:
$ git fsck --connectivity-only --no-dangling --no-progress
$ printf 'exit status: %s\n' "$?"
exit status: 0
This can be substantially quicker. It still checks that referenced blobs exist, and it can find corruption in commits and trees, but it does not detect corruption inside blob contents. It is a connectivity check, not a replacement for a full integrity scan when you need blob validation.
--no-dangling removes the default dangling-object report and avoids work that is irrelevant when you only need to know whether reachable history is connected. Omit it when orphaned history is part of your investigation.
6. Know the safe boundary
Routine fsck is diagnostic. It does not repair a corrupt object. The manual's --lost-found option writes dangling objects below .git/lost-found/, so treat it as a deliberate state-changing action and ensure you have enough disk space before using it. It is not a substitute for backup or for restoring a verified object from another copy.
--strict adds checks for legacy file modes such as a recorded group-writable bit. Older projects can contain objects that trigger this warning even when their history is otherwise usable. Use it when auditing new repositories, and investigate its output rather than applying a blanket ignore.
For automation, test the exit status and retain the diagnostics. A zero status from a connectivity-only run does not certify blob contents. A non-zero status deserves a saved log and a recovery decision, not an automatic prune. No command in this guide requires sudo; if a repository is unreadable, fix its ownership or access through your normal administrative process rather than broadening a script's privileges.
Done means
- You confirmed the repository path before checking it.
git-fsck-objects --full --no-progresscompleted and you recorded its exit status.- You can distinguish missing or mismatched objects from dangling and unreachable history.
- You used
--no-reflogsonly when searching for history hidden by reflog roots. - You understand that
--connectivity-onlydoes not validate blob contents. - You have not deleted objects or created a recovery branch without reviewing the target first.