A Git commit message is part of the commit object. Changing even one character creates a new commit ID; if the commit has descendants, rewriting it recreates those descendants too. That is why correcting a local typo is easy while rewriting a shared branch needs coordination.
Choose the right operation first
Latest commit, not pushed: inspect the index, then
git commit --amend.Older unpublished commit: interactive rebase with
reword.Published private/topic branch: coordinate, fetch, rewrite, and push one ref with an explicit lease.
Published shared/protected branch: normally preserve history; use a new commit or
git revertto undo content. A new commit cannot alter an old message.Accidental code on the wrong branch: save the work on a topic branch and revert the shared branch; do not confuse this with message editing.
Credential or secret exposed: revoke/rotate immediately. Rewriting Git history is only one containment step and does not erase forks, caches or logs.
What amend changes
before
A──B──C ← feature/login
tree + parents + author + committer + message
amend C message
A──B──C′ ← feature/login
new commit ID; same parent B; selected tree; new committer metadata
rewrite older B message
A──B′──C′′ ← feature/login
new B and recreated descendant because its parent ID changedThe old object usually remains recoverable locally for a while, but the branch moves to a new object.
Object-model takeaways
git commit --amendreplaces the branch tip with a newly created commit. It does not edit an immutable object in place.The new commit normally retains the original author and parents, while committer identity/time change unless options alter them.
Any staged changes become part of the amended tree. A “message-only” amend can accidentally include forgotten index content.
Signatures on rewritten commits no longer apply; signed commits must be recreated and re-signed under project policy.
Remote branches and other clones still reference the old history until explicitly updated.
1. Inspect before changing the latest commit
git status --short --branch
git diff --cached --stat
git show --no-patch --format=fuller HEAD
git branch --show-currentPreflight takeaways
git statusreveals branch/tracking state and staged, unstaged or untracked work.git diff --cachedis critical: those staged changes will normally enter the amended commit.git show --format=fullerexposes current message plus author/committer metadata for comparison.Stop if
git branch --show-currentis empty; detached HEAD needs an intentional recovery/branch plan.Check repository policy, commit-signing requirements, protected branches, open reviews and whether anyone already based work on the commit.
2. Change the latest unpublished message
git commit --amendRisk level: caution. Review the command before running it.
Amend takeaways
Without
-m, Git opens the configured editor with the previous message as the starting point.The command creates a new commit from the current index. Unstaged changes remain outside, but staged changes are included.
Commit hooks can run again; do not bypass them reflexively with
--no-verify.If the commit is local-only, no force push is needed. Continue normal development or push it for the first time.
Set a message noninteractively
git commit --amend -m 'fix(auth): validate expired login tokens'Risk level: caution. Review the command before running it.
Message-option takeaways
-msupplies the complete message paragraph. Multiple-moptions form separate paragraphs.Shell quoting matters; avoid interpolation or command substitution in messages built from untrusted input.
A concise subject should describe the change and comply with the project’s convention—not expose issue secrets, tokens or customer data.
Inspect the resulting commit immediately rather than assuming the editor/quoting did what you intended.
3. Verify the local rewrite
git show --stat --format=fuller HEAD
git diff HEAD^ HEAD --
git status --short --branchLocal verification takeaways
Review both metadata and patch. A message-only correction should not unexpectedly alter the tree.
git diff HEAD^ HEADshows the amended commit patch; for a merge commit, parent-specific inspection is needed.Run the same tests and signing/policy checks required for a new commit because the published object will be different.
Keep the terminal/log evidence needed to identify the old and new IDs during coordination.
4. Reword an older unpublished commit
git branch backup/before-message-rewrite
git rebase -i HEAD~4Risk level: caution. Review the command before running it.
Interactive-rebase takeaways
The backup branch is a durable local pointer to the pre-rewrite tip; choose a name that will not be pushed accidentally.
HEAD~4asks Git to replay the last four first-parent commits. Confirm the target ingit log --oneline --decorate.In the todo list, change
picktorewordfor the commit whose message should change. Editing only the displayed subject text besidepickdoes not select rewording.Rebase recreates the selected commit and all descendants in the replay range, changing their IDs.
Ordinary interactive rebase flattens merge structure unless merge-preserving options are deliberately used; inspect history before rebasing complex branches.
Continue or abort safely
git status
git rebase --continue
# Or, to abandon the entire in-progress rewrite:
# git rebase --abortRisk level: caution. Review the command before running it.
Rebase-control takeaways
Resolve conflicts, stage only reviewed resolutions, then continue. Repeat until Git completes.
git rebase --abortreturns to the pre-rebase state while the operation is active; the backup branch remains an additional recovery pointer.Do not start another reset/rebase in the middle because it makes recovery and intent harder to reason about.
After completion, compare
backup/before-message-rewrite...HEADand run tests before considering a remote update.
5. Prefer revert on a shared branch
If the problem is the content of a commit already on main, a revert preserves the public history and adds a new commit applying the inverse patch. It does not delete or rename the original commit.
git fetch origin
git switch main
git pull --ff-only
git revert <bad-commit-id>
git push origin mainRisk level: caution. Review the command before running it.
Revert takeaways
Fetch and fast-forward first so the revert is based on current shared history. Review remote URLs and branch protections.
Replace the placeholder with the exact reviewed commit ID; do not paste angle brackets literally.
Revert can conflict when later commits touched the same lines. Resolve semantically and test.
Reverting a merge requires selecting a mainline parent and has future-merge implications; follow project-specific review rather than guessing
-m.The normal push is fast-forward and preserves coworkers’ commits. This is usually safer for protected/shared branches.
6. Rescue work committed on the wrong branch
Before undoing anything, create a topic branch that points to the accidental commit. Then restore the shared branch with a revert. This preserves the work for a pull request without rewriting main.
git switch main
git branch feature/recovered-work HEAD
git revert HEAD
git push origin main
git push -u origin feature/recovered-workRisk level: caution. Review the command before running it.
Rescue takeaways
The new topic branch captures the accidental commit before main moves forward with a revert.
Review
HEADfirst—this example assumes the accidental commit is exactly the current main tip and has no later commits.The feature branch contains the original change, while main contains both original and revert. A later merge may need careful handling because Git sees the original patch ancestry.
For more complex history, coordinate cherry-pick/revert strategy with maintainers and inspect the graph before commands.
7. Prepare an explicit lease for a topic branch
Only rewrite a published branch when repository policy allows it and every affected collaborator agrees. Capture the exact remote tip you reviewed; this avoids relying solely on a remote-tracking ref that an editor or background job may update behind your back.
branch='feature/login'
git fetch origin "$branch"
expected=$(git rev-parse "origin/$branch")
printf 'Expected remote %s at %s\n' "$branch" "$expected"
git log --oneline --decorate --graph --max-count=12 "origin/$branch" HEADLease-preparation takeaways
Fetching updates your view; inspect commits from coworkers and stop if your rewrite did not incorporate their work.
expectedstores the exact object ID that the remote branch must still have when the push occurs.A background fetch after this point can update
origin/branch, but it cannot alter the explicit ID stored in the shell variable.Keep this shell/session intact or record the expected ID accurately. An empty/wrong value changes the meaning of a lease expression.
Notify reviewers because rewritten commit IDs invalidate old comparisons, approvals, signatures and CI associations.
8. Push exactly one rewritten ref with the lease
branch='feature/login'
# expected must be the reviewed pre-rewrite remote object ID from the previous step.
git push \
--force-with-lease="refs/heads/$branch:$expected" \
origin \
"HEAD:refs/heads/$branch"Risk level: destructive. Review the command before running it.
Force-with-lease takeaways
This is destructive history replacement, but scoped to one destination ref and conditional on its current value.
The server rejects the push if the branch moved away from
expected, protecting work added after the reviewed tip. Do not “fix” rejection with plain--force; fetch, inspect and coordinate.The explicit
<ref>:<expect>form avoids the documented weakness of implicit leases whose remote-tracking refs can be updated by background fetches.HEAD:refs/heads/...makes source and destination explicit; never combine the operation with--all,--mirroror matching refspecs.Remote branch protection, hooks and review policy may correctly reject the update. Obtain approval rather than bypassing controls.
9. Verify the remote after the push
git ls-remote --heads origin refs/heads/feature/login
git fetch origin feature/login
git log --oneline --decorate --graph --max-count=12 origin/feature/login
git status --short --branchRemote-verification takeaways
ls-remoteasks the server which object the named branch currently references. Compare it with the intended local tip.Fetch and inspect the remote-tracking history, then verify CI, pull-request diff, required signatures and reviews.
Tell collaborators to fetch and rebase/reset their local topic work intentionally; do not prescribe a blind reset that destroys their unpushed commits.
Retain the old/new IDs and coordination record until the rewrite and dependent branches are settled.
Removing an unpublished last commit without losing work
git branch backup/before-reset
git reset --soft HEAD^
git status --shortRisk level: caution. Review the command before running it.
Reset-mode takeaways
--softmoves the current branch to the parent while retaining the removed commit’s changes in the index.A default/mixed reset would unstage them;
--hardwould overwrite tracked working-tree/index state and is unnecessary for message cleanup.This is for unpublished history. If collaborators have the commit, prefer coordination/revert or the explicit-lease workflow.
The backup branch and reflog provide recovery pointers until intentionally removed/expired.
Recover a mistaken rewrite
git reflog --date=iso --decorate --max-count=20
git show --stat <old-object-id>
git branch recovery/message-rewrite <old-object-id>Recovery takeaways
The reflog records recent local ref/HEAD movements; retention is finite and reflogs are local to each clone.
Inspect the candidate object before creating a recovery branch. Do not paste placeholders literally.
Creating a branch is non-destructive and makes the object easy to compare/cherry-pick.
If the remote was overwritten, restoring it is another coordinated history rewrite and must protect any newer remote work.
Secrets require incident response, not a nicer message
Immediately revoke/rotate exposed credentials and inspect use; assume a pushed secret may already be copied.
Remove the secret from the working tree and prevent recurrence with secret scanning and safer configuration.
Coordinate repository-wide history cleanup with maintainers using a purpose-built tool and host guidance; all affected refs, tags, forks, PRs, releases and caches need assessment.
Changing a commit message does not remove secrets from file contents or old objects. Deleting one branch is not guaranteed erasure.
Preserve forensic evidence and follow legal/security notification procedures instead of improvising destructive garbage collection.
Troubleshooting map
Amend included unrelated files: staged index was not reviewed; compare with the backup/reflog and reconstruct deliberately.
Non-fast-forward rejected: expected after rewriting; decide whether rewrite is allowed, then use an explicit lease—not plain force.
Lease rejected: remote moved or expectation is wrong; fetch, inspect, incorporate/coordinate, and regenerate the plan.
Protected branch rejects force push: preserve history with revert/new commit or obtain approved administrator workflow.
Interactive rebase omits merges: default rebase linearizes/drops merge commits from the todo model; abort and redesign with maintainers.
Commit signature disappeared: rewritten objects need re-signing and policy checks.
Coworker has old commits: they must preserve their work and consciously rebase/cherry-pick onto the new branch; communicate old/new IDs.
Wrong branch was rewritten: use reflog/backup refs locally, then coordinate any remote repair with explicit expectations.
Safe decision checklist
Identify whether the problem is message, content, branch placement or secret exposure.
Determine whether the commit is unpublished, private-topic published, or shared/protected.
Inspect index, working tree, branch, upstream, remote URL, old/new IDs, signatures and dependent commits.
Create a recovery ref before multi-commit rewrites or resets.
Prefer amend/reword only for unpublished or explicitly coordinated topic history; prefer revert on shared branches.
If pushing rewritten history, capture the reviewed remote OID and update exactly one ref with an explicit lease.
Verify server ref, graph, patch, CI, review/signature state and collaborator recovery instructions.
Related Git guides
Understand undo choices with Git reset, restore and revert explained.
Resolve replay problems using Git rebase conflict recovery.
Protect collaboration with Git branch and upstream workflows.
Primary references
Git documents `git commit --amend`, including index content, parent/author behavior and published-history warnings.
The official `git push` manual defines refspecs,
--force-with-lease=<ref>:<expect>, background-fetch caveats and force risks.Git’s interactive rebase documentation defines
reword,edit, abort/continue behavior and merge handling.The `git reset` manual documents soft/mixed/hard modes and warns against discarding shared commits.
The Git book’s rewriting history guide covers changed commit IDs and the consequences of rewriting published work.
Comments and corrections