Checkpoint Lab — Rebase, Interactive Rebase, Cherry-Pick, Amend, and Safe History Editing
Checkpoint safe history editing by cleaning a messy private topic with amend/fixup/autosquash/reorder, rebasing it onto a moved base, comparing series, cherry-picking an independent fix, and recovering the original tip from reflog.
Learning objectives
- Predict and verify how amend, autosquash, reorder, and base movement replace commit IDs.
- Compare messy, cleaned, and rebased patch-series versions with range-diff.
- Cherry-pick an independent change into another branch without moving its source commit.
- Locate the pre-rewrite topic tip in reflog and preserve it with a recovery branch.
- Document the policy boundary for any future published rewrite and guarded remote replacement.
1. Checkpoint scenario — clean a messy private topic without losing its old tip
You will create a four-commit unpublished topic containing a bad message and a fixup commit, clean it with amend/autosquash/reorder, rebase the cleaned series onto a moved target, compare patch-series versions, cherry-pick an independent fix into another branch, and recover the original messy tip from the branch reflog.
2. Predictions before rewriting
- After amend changes only the latest commit message, will its OID remain the same?
- After autosquash folds a fixup into its target, how many independent topic commits should remain?
-
After rebasing the cleaned topic onto a newly advanced
trunk, will the topic commit OIDs stay stable? - After the rewrite, can the original messy tip still appear in the local branch reflog even though the topic ref no longer points to it?
3. Setup and preflight
Git Bash, Bash, or zsh
mkdir git-rewrite-checkpoint
cd git-rewrite-checkpoint
git init -b trunk
git config user.name "Rewrite Checkpoint"
git config user.email "rewrite-checkpoint@example.invalid"
git config rebase.missingCommitsCheck error
printf "retries=1\ntimeout=5\n" > service.ini
printf "# Retry Service\n" > README.md
printf "alert=normal\n" > alerts.ini
git add service.ini README.md alerts.ini
git commit -m "Create retry service baseline"
git status --short --branch
git log --graph --decorate --oneline --all
PowerShell file-creation alternative
New-Item -ItemType Directory git-rewrite-checkpoint | Out-Null
Set-Location git-rewrite-checkpoint
git init -b trunk
git config user.name "Rewrite Checkpoint"
git config user.email "rewrite-checkpoint@example.invalid"
git config rebase.missingCommitsCheck error
@('retries=1','timeout=5') | Set-Content service.ini
Set-Content README.md '# Retry Service'
Set-Content alerts.ini 'alert=normal'
git add service.ini README.md alerts.ini
git commit -m "Create retry service baseline"
git status --short --branch
git log --graph --decorate --oneline --all
4. Create the deliberately messy unpublished topic
git switch -c topic-retry
# Change retries=1 to retries=3 in service.ini
git add service.ini
git commit -m "Add configurable retry count"
RETRY_COMMIT=$(git rev-parse HEAD)
# Add a Retry section to README.md
git add README.md
git commit -m "WIP docs"
WIP_OID=$(git rev-parse HEAD)
# Prediction: amend replaces WIP_OID
git commit --amend -m "Document retry behavior"
DOC_OID=$(git rev-parse HEAD)
# Add timeout_backoff=exponential to service.ini
git add service.ini
git commit --fixup="$RETRY_COMMIT"
printf "retry smoke test\n" > tests.txt
git add tests.txt
git commit -m "Add retry smoke test"
PRE_CLEAN=$(git rev-parse HEAD)
OLD_BASE=$(git rev-parse trunk)
git log --reverse --format='%H %s' trunk..topic-retry
git reflog -8 topic-retry
Verify prediction 1: WIP_OID and
DOC_OID differ because amend created a replacement
commit.
5. Autosquash and reorder the review series
topic-retry is
intentionally unpublished. Do not perform this exercise on a branch
collaborators consume.
git status --short
git rebase -i --autosquash trunk
In the todo editor, Git should move the fixup! line
directly after Add configurable retry count. Keep it as
fixup. Reorder the remaining commits so the final story
is:
pick Add configurable retry count
fixup fixup! Add configurable retry count
pick Add retry smoke test
pick Document retry behavior
Save and exit. Then verify:
CLEAN_TIP=$(git rev-parse HEAD)
git log --reverse --format='%H %s' trunk..topic-retry
git diff --check trunk...topic-retry
git range-diff "$OLD_BASE..$PRE_CLEAN" "trunk..topic-retry"
Verify prediction 2: four old topic commits become three review commits because the fixup is folded into its target.
6. Advance trunk, then rebase the cleaned topic
CLEAN_BASE=$(git rev-parse trunk)
git switch trunk
# Append owner=platform to service.ini without changing retry lines.
git add service.ini
git commit -m "Record service ownership"
NEW_BASE=$(git rev-parse HEAD)
git switch topic-retry
PRE_BASE_REBASE=$(git rev-parse HEAD)
git status --short
git rebase trunk
POST_BASE_REBASE=$(git rev-parse HEAD)
git log --graph --decorate --oneline --all --max-count=16
git range-diff "$CLEAN_BASE..$PRE_BASE_REBASE" "$NEW_BASE..$POST_BASE_REBASE"
Verify prediction 3: the final topic content/intent
can stay equivalent while its commits receive new IDs because their
parent chain now starts from NEW_BASE.
7. Create and cherry-pick one independent fix
git switch trunk
git switch -c alert-fix
# Change alerts.ini from alert=normal to alert=verbose
git add alerts.ini
git commit -m "Increase retry alert visibility"
ALERT_FIX=$(git rev-parse HEAD)
git switch trunk
git switch -c maintenance
git status --short
git cherry-pick "$ALERT_FIX"
git show --stat --oneline HEAD
git log --graph --decorate --oneline --all --max-count=18
The source alert-fix commit remains where it was.
maintenance receives a new commit that replays its
change.
8. Recover the original messy pre-clean tip through reflog evidence
Return to the topic and inspect its local branch reflog:
git switch topic-retry
git reflog show --date=local --format='%H %gs' topic-retry
Confirm that the saved PRE_CLEAN OID appears in the
reflog output. Then derive the recovery OID from the reflog itself
and preserve it:
RECOVER_OID=$(git reflog show --format='%H %gs' topic-retry | awk -v wanted="$PRE_CLEAN" '$1==wanted {print $1; exit}')
test -n "$RECOVER_OID"
git branch recovered-pre-clean "$RECOVER_OID"
git show --no-patch --oneline recovered-pre-clean
git log --graph --decorate --oneline --all --max-count=22
PowerShell equivalent for selecting the matching reflog line:
$match = git reflog show --format='%H %gs' topic-retry | Select-String $PRE_CLEAN | Select-Object -First 1
$RECOVER_OID = ($match.ToString() -split ' ')[0]
git branch recovered-pre-clean $RECOVER_OID
git show --no-patch --oneline recovered-pre-clean
Verify prediction 4: the main topic ref points to rewritten history, while the new recovery branch makes the old messy tip explicitly reachable again.
9. Produce a compact rewrite report
printf "old_messy_tip=%s\n" "$PRE_CLEAN"
printf "clean_before_base_move=%s\n" "$PRE_BASE_REBASE"
printf "new_target=%s\n" "$NEW_BASE"
printf "final_topic_tip=%s\n" "$POST_BASE_REBASE"
printf "recovered_old_tip=%s\n" "$(git rev-parse recovered-pre-clean)"
git log --reverse --format='%H %s' trunk..topic-retry
git diff --check trunk...topic-retry
git diff --stat trunk...topic-retry
In production, this kind of old/new OID mapping is useful when a review system or CI record needs to explain that a patch series was replaced.
10. If the topic had been published, stop before remote replacement
This lab intentionally has no remote. If team policy allowed rewriting a published review branch, the safe workflow would first fetch/inspect the remote and record the exact expected remote OID. Only then would a guarded update be considered:
# Conceptual policy pattern; do not run in this no-remote lab.
EXPECTED=<verified-old-remote-topic-oid>
git push --force-with-lease=refs/heads/topic-retry:$EXPECTED origin topic-retry:topic-retry
A lease failure is a stop signal, not permission to switch to
--force.
11. Verification checklist
-
The lab repository is disposable and uses fake
.invalididentity data. - The original topic had four commits after the baseline: implementation, amended documentation, fixup, and test.
- Amend changed the documentation commit OID.
- Autosquash folded the fixup into its target and the todo reorder produced a three-commit review series.
-
range-diffcompared the messy and cleaned series. - After trunk advanced, rebase recreated the cleaned topic on the new base and a second range-diff compared versions.
-
An independent alert fix was cherry-picked into
maintenancewithout moving the source branch. -
The original messy tip appeared in the topic reflog and was
preserved as
recovered-pre-clean. - No shared remote history was rewritten and no plain force push was used.
12. Cleanup
git-rewrite-checkpoint.
Git Bash / Bash / zsh
git status --short --branch
cd ..
pwd
rm -rf git-rewrite-checkpoint
PowerShell
git status --short --branch
Set-Location ..
Get-Location
Remove-Item -Recurse -Force git-rewrite-checkpoint
13. Knowledge check
Question 1. Why did the autosquash cleanup reduce four topic commits to three?
Question 2. Why did rebasing the already-cleaned topic onto the moved trunk create another set of commit IDs?
Question 3. How did reflog help recover the pre-clean history?
Question 4. Why is the cherry-picked maintenance fix a different commit from the source fix?
Question 5. A published rewrite needs a force update. Why not
use plain --force?
14. What Chapter 09 adds to a production Git operating model
You can now separate private history cleanup from shared-history governance, compare old/new patch series, transplant selected commits intentionally, abort uncertain sequencer operations, preserve old tips through reflog, and describe a guarded remote replacement policy. The goal is not “perfectly linear Git history”; it is controlled provenance with reviewable changes and recoverable decisions.
15. Chapter checkpoint summary
Rebase, interactive rebase, cherry-pick, and amend are all forms of graph reconstruction. Their power comes from creating new commits and moving refs. Their risk comes from doing that after other people or systems have made the old OIDs part of shared reality.
Authoritative references
git-rebase
git-commit
git-range-diff
git-cherry-pick
git-reflog
git-push
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.