Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Git: Recovering Abandoned Commits

Learn how to recover existing commits after local history movement by using reflogs first, git fsck as a fallback investigation tool, and a new reference to preserve the recovered object.

Levels: Advanced ~40 min read

Advanced

Learner goal

By the end of this lesson, you should be able to recover an existing commit after local history movement: find it through a reflog when possible, investigate remaining unreachable objects with `git fsck` when reflog information is unavailable, reattach the recovered object to a new reference, and verify that the recovered commit itself did not change.

bash
reflog → first locator for previous local ref values
git fsck → investigate remaining unreachable objects
git branch recovered <commit> → make an existing commit reachable again
verify → object ID, snapshot, and graph state

Quick check

A branch was reset backward and a wanted commit is no longer the branch tip. What should you normally inspect first?

A local branch tip has moved backward.The earlier reference value can be resolved from the reflog.

What “abandoned” means in Git

In this lesson, an abandoned commit is an existing commit object that is no longer reachable from the repository’s current normal references such as branches and tags. “Abandoned” does not mean “already deleted from the object database.” A commit can remain recoverable for some time after its last useful reference disappears.

This is a reachability problem, not a command-failure problem. The important question is not whether a branch name still exists; it is whether the commit object you need is still present and can be identified.

bash
git rev-parse HEAD
git log --oneline --decorate --graph --all -8

Quick check

Which statement is accurate after a branch reset makes an earlier commit unreachable?

A reference no longer points to the wanted commit.The commit may still be present and recoverable.

Recovery path 1: use the reflog

V453 established the key idea: a reflog records earlier values of a local reference. That makes it the first recovery locator after a local reset, branch movement, or similar reference update. Do not guess a commit message or recreate the work yet; first inspect the recorded reference movement.

bash
git reflog main -10
git reflog HEAD -10
git rev-parse "main@{1}"

Quick check

After `git reset --hard HEAD~1` on `main`, what can `main@{1}` identify?

main was moved backward and its reflog still contains the prior value.`main@{1}` resolves to the prior recorded tip.

Turn the recovered object into a durable reference

Once you have the correct commit object name, create a new reference so the object becomes reachable again. A branch is a practical recovery label. `git branch recovered <commit>` creates the branch at the supplied start point; it does not rewrite the recovered commit.

bash
recovered=$(git rev-parse "main@{1}")
git branch recovered "$recovered"
git rev-parse recovered
git show --no-patch --format="%H %s" recovered

Quick check

Why does creating `recovered` help?

You have identified the wanted commit object ID.A new branch points to that same object.

Recovery path 2: investigate with `git fsck`

When reflog information is unavailable, you need an object-database investigation step. The official `git fsck` command checks object connectivity and can report objects that are unreachable from its selected heads. With no explicit heads, Git normally considers refs and reflogs among those heads.

bash
git fsck --unreachable --no-reflogs --no-progress

Quick check

Why does this recovery lesson pair `--unreachable` with `--no-reflogs`?

The recovery scenario assumes reflog-based discovery is unavailable.`fsck` scans reachability without using reflogs as roots and reports remaining unreachable objects.

Read the `fsck` result carefully

Look specifically for an `unreachable commit <object>` or a `dangling commit <object>` that matches the history you are trying to recover. “Unreachable” says the object is not reachable from the specified heads. “Dangling” says the object is present but is not directly used by another object; the official documentation notes that a dangling commit can itself be a root of a history segment.

bash
git fsck --no-reflogs --unreachable --no-progress | grep "unreachable commit"
git show --no-patch --format="%H%n%P%n%s" <commit>

Quick check

What does `dangling commit <id>` tell you?

`git fsck` reports a dangling commit object.The object is present and may be inspected or reattached.

Make the recovery proof explicit

A recovery command succeeding is not enough. Verify the recovered object ID, inspect its commit metadata and snapshot, and confirm that the new reference points to the exact same object. The strongest simple proof is identity: the recovered reference resolves to the object ID you intended to save.

bash
git rev-parse recovered
git show --stat --oneline recovered
git log --oneline --decorate --graph recovered -6
git status --short --branch

Quick check

Which check proves that the recovered branch points to the same commit object you found?

A recovery object ID has been selected and a branch has been created.The branch resolves to the identical object ID.

What recovery cannot promise

Recovery depends on the object still being present. Reflog entries expire, and Git may eventually prune unreachable objects. The official Git configuration documentation lists defaults of 90 days for normal reflog expiration and 30 days for reflog entries that are both older and unreachable. Those values are defaults, not a promise that every repository will retain every object for those exact periods.

bash
git config --get gc.reflogExpire
git config --get gc.reflogExpireUnreachable

Quick check

Why is time a real recovery boundary?

A wanted commit is no longer reachable from current refs.Recovery remains possible only while useful evidence and the underlying object still exist.

Disposable recovery laboratory

Practice both recovery paths in separate disposable repositories. In the first, make three commits on `main`, reset `main` backward, resolve `main@{1}`, create a `recovered` branch at that object, and verify that the object ID and committed snapshot match the pre-reset commit. In the second, create a temporary branch containing a wanted commit, delete that branch, expire all reflog entries in the disposable repository to model unavailable reflog evidence, run `git fsck --no-reflogs --unreachable`, identify the abandoned commit, create a recovery branch from it, and verify the exact object ID and snapshot.

bash
git reflog main -10
git rev-parse "main@{1}"
git branch recovered "main@{1}"
git show --stat --oneline recovered

# Fallback laboratory only:
git fsck --no-reflogs --unreachable --no-progress
git branch recovered-fsck <commit>
git show --stat --oneline recovered-fsck

Quick check

After `git fsck` finds a wanted unreachable commit, what should you do next before treating the recovery as complete?

`git fsck` has identified a candidate unreachable commit.A recovery ref preserves the existing object, followed by explicit verification.

Official-source boundary

This lesson uses only official Git project documentation: `git-reflog` and `gitrevisions` for reflog recovery, `git-fsck` for unreachable-object investigation, `git-branch` for creating a recovery reference, and the official Git book’s Maintenance and Data Recovery chapter for the documented recovery pattern. The live official documentation was rechecked on 2026-10-01. The current `gitrevisions` manual is Git 2.56.0; the `git-fsck` manual is maintained through Git 2.53.0. Foxipa’s local verifier is Git 2.47.3, so execution evidence is reported for that installed executable rather than silently generalized to every Git release.

Was this page helpful?

Mark this learning resource complete to track your learning progress.