Clean up historyAlways fixable

Change the contents of an old commit

How do I edit a commit that isn't the most recent one?

Short answer

Mark the commit edit in git rebase -i. Git stops there, you make your changes and amend, then git rebase --continue replays the rest. The tidier route is git commit --fixup plus an autosquash rebase.

quick fix
git rebase -i HEAD~3
# set 'edit' on the target, then amend and continue

Pause history at a commit so you can modify it in place

Does this match your situation?

  • You forgot a file in a commit three commits back.
  • An old commit contains a debug statement or a typo.
  • A reviewer asked you to change something in an earlier commit of the series.

Step-by-step fix

  1. The clean way: commit a fixup and autosquash

    Make the correction now as a normal change, label it as a fixup for the target commit, then let rebase fold it in automatically. No manual editing of the rebase list at all.

    step 1
    git add src/app.ts
    git commit --fixup a1b2c3d
    git rebase -i --autosquash a1b2c3d~1
    # the list is pre-arranged; just save and close
    
  2. The manual way: stop at the commit

    Mark it edit and the rebase pauses with that commit checked out, leaving you in an ordinary working state.

    step 2
    git rebase -i HEAD~3
    
    #   pick a1b2c3d Older commit
    #   edit f4e5d6c The one to change     <- changed from pick
    #   pick 9a8b7c6 Newer commit
    
  3. Make your changes and amend

    Edit files, stage them, and amend — this replaces the paused commit rather than adding a new one after it.

    step 3
    git status                      # you are AT that commit now
    # edit files...
    git add src/app.ts
    git commit --amend --no-edit
    
  4. Continue the rebase

    The remaining commits replay on top of your amended one. Resolve conflicts if the later commits touched the same lines.

    step 4
    git rebase --continue
    git log --oneline -5
    
  5. Push the rewritten branch

    Every commit from the edited one onwards has a new hash.

    step 5
    git push --force-with-lease
    

    Only on branches you own. Coordinate first if anyone else has pulled them.

Why this works

Commits are immutable — you never truly edit one. Interactive rebase replays your history and, when it reaches a commit marked edit, hands control back with that commit checked out and its changes applied. Amending at that moment creates a replacement commit, and continuing replays everything after it onto the new parent. The result looks like an in-place edit but is really a rebuild, which is exactly why all the hashes downstream change.

How to stop it happening again

  • Use git commit --fixup as soon as you spot a problem, then autosquash before pushing.
  • Set rebase.autoSquash true globally so --autosquash is implied.
  • Review with git diff --staged so fewer commits need fixing at all.

Commands used in this guide

git rebase -i

Reorder, squash, split, reword or drop your recent commits.

git commit --amend

Replace the most recent commit instead of stacking another one on top.

git commit

Record everything currently staged as a permanent snapshot.

git push

Upload your commits to the remote repository.

Still stuck?

Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.

Browse all guides →

Frequently asked questions

How do I edit an old commit in Git?

Run git rebase -i with a range covering it, change its action to edit, make your changes when the rebase pauses, run git commit --amend, then git rebase --continue. Everything after it is replayed onto the amended commit.

What is git commit --fixup?

It creates a commit whose message marks it as a fix for a specific earlier commit. Running git rebase -i --autosquash then positions it directly after its target with the fixup action already set, so folding it in requires no manual editing.

Is editing old commits safe?

On a private branch, entirely - the originals stay in the reflog if you need them back. On a shared branch it rewrites history others have pulled, so either coordinate a force-push or add a normal follow-up commit instead.

Related rescue guides

← All Git Rescue guides