Recovery

Recovering from a broken interactive rebase

Common errors during interactive rebase (wrong actions, conflicts, editor issues) and how to recover, including --abort, --edit-todo, and reflog-based recovery.

Who This Is For
  • Anyone actively handling a Git mistake
  • Readers who want a conservative rescue habit before trouble happens
Prerequisites
  • Stop mutating the repo further
  • Be ready to inspect `git reflog`, `git status`, and `git log --graph`
Common Risks
  • Running more reset or rebase commands before preserving a checkpoint
  • Changing shared history before assessing blast radius

The short version

Interactive Rebase Commit RearrangementInteractive rebase lets you reorganize, modify, squash, or drop commits during replay. When things go wrong, Git provides --abort, --edit-todo, and reflog recovery.
Before rebase (original chain)
main
ABCD
feature
BEF
After rebase (rearranged chain)
main
ABCD
feature
DE'F'

Interactive rebase (git rebase -i) lets you reorder, modify, squash, or drop commits while replaying them. When things go wrong, Git provides --abort, --edit-todo, and reflog as layered recovery mechanisms.

What interactive rebase does

Before rebase:
A --- B --- C --- D --- E (feature)
       \
        X --- Y (main)

After rebase:
A --- B --- C --- D --- E (feature, old, to be discarded)
       \
        X --- Y --- B' --- C' --- D' --- E' (feature, new)

Interactive rebase opens an editor listing the commits to replay, each with an action prefix:

pick B    apply commit B
pick C    apply commit C
pick D    apply commit D
pick E    apply commit E

# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like squash, but discard this commit's log message
# d, drop <commit> = remove commit

Scenario 1: Conflict during rebase

Like a normal rebase or cherry-pick, conflicts can occur when replaying a commit.

$ git rebase -i HEAD~4
# After saving the editor...

$ git rebase main
Auto-merging src/auth.js
CONFLICT (content): Merge conflict in src/auth.js
error: could not apply abc1234... feat: update auth logic
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit with "git rebase --skip".
hint: To abort and get back to the original branch before "git rebase",
hint: run "git rebase --abort".

$ git status
interactive rebase in progress; onto def5678
Last command done (1 command done):
   pick abc1234 feat: update auth logic
Next commands to do (3 remaining commands):
   pick bcd2345 fix: correct edge case
   squash cde3456 feat: add error handling
  (use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'feature' on 'def5678'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   src/auth.js

Your four options:

Option A: Resolve conflicts and continue

# 1. Edit conflicted files
vim src/auth.js

# 2. Mark as resolved
git add src/auth.js

# 3. Continue
git rebase --continue
# Git may open an editor for the commit message (for edit/reword actions)

Option B: Skip the current commit

# Don't apply this conflicting commit, move on to the next
git rebase --skip

Option C: Abort entirely

# Go back to the pre-rebase state
git rebase --abort

Option D: Modify the rebase plan

# Open the editor to modify the remaining rebase plan
git rebase --edit-todo
# For example, change a pick to drop or squash
# Save and continue
git rebase --continue

Scenario 2: Wrong action in the rebase editor

Accidentally wrote drop instead of pick

# You meant to pick this commit but typed drop by mistake
drop abc1234 feat: important new feature  ← this commit gets discarded!

Recovery:

# Method 1: If rebase is still in progress
git rebase --abort

# Method 2: If rebase already finished, use reflog
git reflog
# Find the pre-rebase state
# git reset --hard feature@{1}  or
# git reset --hard <pre-rebase-SHA>

Lost commit info after squash

# Squash combines commit messages, but you might accidentally delete important descriptions
pick abc1234 feat: base framework
squash bcd2345 fix: correct issue

After squash, the editor opens for the combined message. If you saved an incomplete message:

# Amend the most recent commit message
git commit --amend

# If rebase is already complete
git rebase -i HEAD~1  # use reword to fix

Stuck after an edit action

# You chose edit for a commit, rebase stopped:
$ git status
interactive rebase in progress; onto def5678
Last command done (1 command done):
   edit abc1234 feat: update auth logic
  (use "git commit --amend" to amend the commit)
  (use "git rebase --continue" to continue)
# 1. Make your changes
vim src/auth.js
git add src/auth.js

# 2. Amend the commit message (optional)
git commit --amend

# 3. Continue rebase
git rebase --continue

Scenario 3: Editor problems

Don't know how to use the editor

Interactive rebase uses your default editor. If you're unfamiliar with Vim:

# Temporarily use a different editor
GIT_SEQUENCE_EDITOR="code --wait" git rebase -i HEAD~4

# Or set a global default editor
git config --global core.editor "code --wait"  # VS Code
git config --global core.editor "nano"          # nano
git config --global core.editor "vim"           # vim

Rebase errors after saving the editor

$ git rebase -i HEAD~4
error: invalid line 3: blahblah blahblah
Could not execute editor

This usually means the rebase todo file has a syntax error. Git tells you which line is wrong.

# Fix it
git rebase --edit-todo
# Correct the bad line (ensure action is pick/reword/edit/squash/fixup/drop)
git rebase --continue

Scenario 4: Rebase completed but result is wrong

Rebase finished cleanly, but the outcome isn't what you wanted.

Use reflog to recover the pre-rebase state

# Check the reflog
$ git reflog
a1b2c3d (HEAD -> feature) HEAD@{0}: rebase (finish): returning to refs/heads/feature
a1b2c3d HEAD@{1}: rebase (pick): feat: add error handling
b2c3d4e HEAD@{2}: rebase (pick): fix: correct edge case
c3d4e5f HEAD@{3}: rebase (pick): feat: update auth logic
d4e5f6a HEAD@{4}: rebase (start): checkout main
e5f6a7b HEAD@{5}: checkout: moving from main to feature  ← pre-rebase position!
e5f6a7b (feature@{1}) feat: last commit (before rebase)

# Return to pre-rebase state
git reset --hard e5f6a7b
# or
git reset --hard feature@{1}

Partial recovery

If only a specific commit is wrong, find its old SHA in the reflog and cherry-pick the correct version:

# Find the old commit SHA in reflog
git reflog --all | grep "important commit message"

# Cherry-pick the old version
git cherry-pick <old-sha>

Scenario 5: Rebased onto the wrong branch

# Accidentally ran
git rebase -i main   # meant to rebase onto develop

# Recovery
git rebase --abort   # if still in progress

# If already finished
git reset --hard feature@{1}  # back to before rebase
git rebase -i develop          # rebase onto the correct branch

Interactive rebase command quick reference

CommandPurpose
git rebase --continueContinue after resolving conflicts or editing
git rebase --abortCancel entirely, return to pre-rebase state
git rebase --skipSkip the current commit
git rebase --edit-todoEdit the remaining rebase plan
git rebase --quitStop rebase but keep current progress (don't return to pre-rebase)

Difference between --quit and --abort:

  • --abort: fully returns to the pre-rebase state
  • --quit: stops rebase but keeps already-replayed commits on the current branch

Preventive measures

1. Create a backup branch before rebasing

# The most important preventive step!
git branch backup/feature-before-rebase

If the rebase goes wrong, you can always:

git reset --hard backup/feature-before-rebase

2. Preview commits before rebasing

# See what commits will be rebased
git log --oneline main..feature
# Confirm the list of commits to rebase

3. Experiment on a copy

# Create a copy branch
git checkout -b feature/rebase-trial
# Experiment with rebase on the copy
git rebase -i HEAD~4
# Once satisfied, delete original and rename the copy
git branch -D feature
git branch -m feature

4. Automate with GIT_SEQUENCE_EDITOR

If you know what operations you need, use a script instead of manual editing:

# Squash the 3rd commit
GIT_SEQUENCE_EDITOR="sed -i '3s/pick/squash/'" git rebase -i HEAD~4

# Drop all commits containing "WIP"
GIT_SEQUENCE_EDITOR="sed -i '/WIP/s/pick/drop/'" git rebase -i HEAD~10

Quick decision flowchart

Rebase went wrong?
      │
  ┌───┴───┐
  Still in progress?   Already finished?
  │            │
  ↓            ↓
  Conflict?   Recover via reflog
  │            │
  ├─ Resolve → --continue   git reflog
  ├─ Skip → --skip          git reset --hard <old-sha>
  └─ Give up → --abort