Git, CI/CD & GitOpsXVIII · Git RecoveryRecovery
Recovering an amended commit — the previous commit is in the reflog
What you'll learn
- Apply the reflog recipe to recover a commit that has been amended with `git commit --amend`
- Identify the original OID at `HEAD@{1}` as the recovery target and recognise that it becomes a dangling commit after the amend
- Distinguish `git cherry-pick <oid>` (replay the original commit on the current branch) from `git branch <name> <oid>` (preserve the original commit as a named branch)
- Recognise the 90-day retention boundary on the reflog entry and the recovery paths past the window
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
A git commit --amend is the most common recovery scenario
because the amend is the most common history-rewriting
command. The amend rewrites the current commit’s OID, the
branch pointer advances to the new OID, and the original
OID becomes a dangling commit in the object store. The
dangling commit is reachable via the reflog at HEAD@{1}
and is recoverable for the 90-day default window.
The surprise is what the original OID becomes. Engineers often believe the amend “edits” the commit; the data model shows otherwise. The amend creates a new commit and orphans the original. The original is gone from the branch view but preserved in the object store.
What the amend actually does
git commit --amend is shorthand for three operations: keep
the current commit’s parent, keep the current commit’s
author (unless --reset-author is passed), and replace the
commit’s tree with the new index. The result is a new
commit with the same parent and author but a new tree and
therefore a new SHA. The branch pointer is moved to the new
commit; the original commit is no longer reachable from the
branch.
flowchart LR
A["original commit (8a3f9d2)"] --> B["parent commit"]
A --> C["amend: new tree from index"]
C --> D["new commit (a1b2c3d)"]
B --> D
A -. "after amend" .-> E["dangling in object store"]
A -. "reflog" .-> F["HEAD@{1} = 8a3f9d2"]
D --> G["branch tip"]
E -->|"git cherry-pick"| H["replay on current branch"]
E -->|"git branch name"| I["preserve as branch"]
The fork in the diagram is the recovery path. The original
commit is preserved in two places: the object store (as a
dangling commit) and the reflog (as HEAD@{1}). The
recovery is to read the reflog, copy the OID, and either
cherry-pick or branch from it.
The recovery recipe
# Step 1: locate the original commit before the amend
git reflog -5
# a1b2c3d HEAD@{0}: commit (amend): rotate IAM credentials <-- the amend
# 8a3f9d2 HEAD@{1}: commit: rotate IAM credentials <-- the original
# 3e4f5a6 HEAD@{2}: commit: break out IAM role into module
# Step 2: copy the OID to a durable location
ORIGINAL_OID=$(git reflog -1 HEAD@{1} | awk '{print $1}')
echo "Original commit: $ORIGINAL_OID"
# Step 3: verify the OID is the right one
git show --stat $ORIGINAL_OID
# confirms the commit before the amend
# Step 4: recover via cherry-pick or branch
git cherry-pick $ORIGINAL_OID
# or
git branch feature/iam-rotation-pre-amend $ORIGINAL_OID
The recipe has the same four-step shape as the other
recovery recipes. The first command is git reflog. The
recovery command is git cherry-pick or git branch.
git cherry-pick versus git branch
The two recovery commands have different shapes:
flowchart LR
A["original OID (8a3f9d2)"] --> B["git cherry-pick 8a3f9d2"]
A --> C["git branch name 8a3f9d2"]
B --> D["new commit on current branch"]
B --> E["tree changes replayed"]
B --> F["author and message preserved"]
C --> G["branch at 8a3f9d2"]
C --> H["original commit reachable"]
C --> I["no new commit created"]
git cherry-pick <oid>replays the tree changes of the original commit on the current branch as a new commit. The parent is the current branch tip; the tree is the original commit’s tree; the author and message are the original commit’s author and message. The cherry-pick is the additive recovery: the original commit is preserved semantically on the current branch.git branch <name> <oid>creates a new branch pointing at the original commit. The original commit is reachable via the named branch; no new commit is created. The branch is the preservation recovery: the original commit is preserved as a recoverable reference.
The branch form is preferred when the engineer wants to preserve the original commit for comparison or audit. The cherry-pick form is preferred when the engineer wants to fold the original commit back into the working branch.
The case where the engineer wants both branches
The most common production scenario is: the amend was a mistake (the engineer amended the wrong commit or amended with the wrong changes), and the engineer wants both the amended commit and the original commit available. The recovery is the branch form:
# Preserve the original as a branch
git branch feature/iam-rotation-pre-amend $ORIGINAL_OID
# The current branch is unchanged; the amended commit is the tip
git log --oneline -3
# a1b2c3d HEAD@{0}: commit (amend): rotate IAM credentials
# 7e8f9a0 HEAD@{1}: commit: bump ansible collection version
# 3e4f5a6 HEAD@{2}: commit: break out IAM role into module
# The original is on the recovery branch
git log --oneline -3 feature/iam-rotation-pre-amend
# 8a3f9d2 commit: rotate IAM credentials
# 7e8f9a0 commit: bump ansible collection version
# 3e4f5a6 commit: break out IAM role into module
The branches are now divergent. The engineer can compare
the two commits (git diff feature/iam-rotation feature/iam-rotation-pre-amend), merge one into the other,
or pick commits from one.
Recovery past the reflog window
Past the 90-day reflog window, the original commit is an unreachable object in the object store. The recovery paths are:
- Another clone. Any clone that fetched the branch before the amend may still have the OID in its reflog.
- Object store scan.
git fsck --unreachable --no-reflogson a clone that has the objects lists the dangling commit. The recovery isgit branch recovered <oid>. - Remote refs. The commit may be referenced by the forge’s PR ref, an older CI artifact, or a release tag.
- Backup. The bytes may be in a CI artifact store or a configuration backup.
The order of preference is the same as for the deleted branch. The reflog is the first path; the durable backup is the last.
Production discipline
- Never amend a pushed commit without coordinating with the team. The amend rewrites the public OID; any clone that fetched the branch has the old OID and will produce a non-fast-forward push or a forced merge on the next fetch. The team needs to be notified before the amend.
- Always copy the OID to a durable location before the
amend. The OID at
HEAD@{1}before the amend is the recovery target; copying it to a PR comment means the recovery is possible even if the reflog expires. - Prefer
git branch <name> <oid>overgit cherry-pick <oid>for recovery. The branch form preserves the original commit as a named branch; the cherry-pick form creates a new commit on the current branch. The branch form is recoverable past the reflog window via the named branch; the cherry-pick form is not. - Document the recovery in the runbook. The recipe above is a one-page runbook entry; paste it into the team’s on-call documentation.
Cross-course references
- Git, CI/CD & GitOps — Part XII (Amend) — the amend mechanics; the prerequisite for this lesson.
- Git, CI/CD & GitOps — Part XVII (Reflog) — the reflog’s location and scope; the prerequisite for the reading step.
- GitOps with Argo CD — Part VI (MergeStrategies) — the GitOps controller’s commit lifecycle; the controller does not amend commits because the manifests are the source of truth, but the recovery recipe is the same when an operator amends locally.
Quiz
Knowledge check · 4 questions
Q1. An engineer has just run `git commit --amend` and realised the original commit should have been preserved. The branch has not been pushed. What is the precise sequence to recover the original commit?
Q2. After `git commit --amend`, the original commit's OID becomes a dangling commit in the object store and is reachable via the reflog at `HEAD@{1}` for the 90-day default retention window.
Q3. What is the difference between `git cherry-pick <oid>` and `git branch <name> <oid>` for recovering an amended commit?
Q4. Walk the recovery for an engineer who has amended the wrong commit and needs both the original and the amend available.
An engineer on `feature/iam-rotation` has run `git commit --amend` because they wanted to add a forgotten Terraform change to the previous commit. The amend succeeded but the engineer then realised the original commit had the correct message and the amend introduced a typo. The branch has not been pushed. The engineer needs to preserve the original commit for comparison and to create a follow-up commit that fixes the typo.
Passing score: 75%. Answers are checked in this browser.