Git Interactive Rebase

GIT Tutorials


Git interactive rebase lets you rewrite a sequence of commits before you share or merge them. You can improve commit messages, combine small corrections, reorder work, split a large commit, or remove an unwanted commit.

Rebasing recreates the affected commits, so their commit IDs change. Use interactive rebase freely on private local work. If the commits are already shared, coordinate with the team before rewriting them.

Create a temporary backup branch before a complex rewrite. It gives you a simple reference even though Git also records earlier branch positions in the reflog.

Start an Interactive Rebase

Run git rebase with -i and identify the commit immediately before the range you want to edit.

Example:

# Rewrite the latest three commits
git branch backup/profile-history
git rebase -i HEAD~3

You can also provide an upstream branch. Git then lists commits that belong to your current branch but are not reachable from that upstream.

# Rewrite local feature commits created after branching from main
git rebase -i main

The editor shows commits from oldest to newest because Git replays the todo list from top to bottom. The upstream commit itself is not included.

Interactive Rebase Commands

Command Purpose
pick Keep the commit
reword Keep changes and edit the message
edit Pause to amend or split the commit
squash Combine with the previous commit and edit messages
fixup Combine with the previous commit and discard this message
drop Remove the commit
exec Run a shell command
break Pause at this position

Reorder, Reword, or Remove Commits

Move a line to reorder a commit. Replace pick with reword to edit only its message, or with drop to remove it. Reordering can cause conflicts when one commit depends on another.

Example todo list:

# Keep the feature, rename the test commit, and remove debugging
pick 91ac341 Add user profile
reword c96a281 Add profile tests
drop 518d732 Add temporary debugging

Squash Related Commits

Place a correction directly below its target and change its action to squash or fixup. Squash opens the combined message for editing; fixup discards the correction's message.

# Produce one focused feature commit
pick 91ac341 Add user profile
fixup 518d732 Fix profile heading
squash c96a281 Add missing profile validation

Use Autosquash

Create a targeted fixup commit, then let --autosquash move it beside the correct commit and mark it as fixup.

# Stage the correction and link it to an earlier commit
git add src/profile.php
git commit --fixup 91ac341
git rebase -i --autosquash main

Edit or Split a Commit

Change pick to edit. When Git pauses, modify files and amend the commit. To split it, reset the paused commit while keeping its changes, then create several smaller commits.

# Split the paused commit while keeping its changes in the working tree
git reset HEAD^

# Create the first focused commit
git add src/profile.php
git commit -m "Add profile model"

# Create the second focused commit
git add tests/profile_test.php
git commit -m "Test profile model"

# Continue replaying the remaining commits
git rebase --continue

Handle Rebase Conflicts

Git stops when it cannot apply a commit cleanly. Open the conflicted files, remove conflict markers, keep the correct content, stage the resolved files, and continue.

# See conflicted paths
git status

# Stage each resolved file and continue
git add src/profile.php
git rebase --continue

Use git rebase --skip only when the current commit is no longer required. Use git rebase --abort to restore the branch to its pre-rebase state.

Run Tests During the Rebase

The exec action or --exec option runs a command after selected commits. Git pauses when the command fails, allowing you to fix the problem before continuing.

# Verify every rewritten commit
git rebase -i --exec "npm test" main

Recover from an Incorrect Rebase

If a completed rebase produced the wrong history, inspect git reflog. Find the branch position recorded before the rebase and create a recovery branch from it.

# Locate the earlier branch tip
git reflog

# Preserve the chosen earlier position
git branch recover-profile HEAD@{5}

Push Rewritten History Safely

A normal push is rejected when the remote branch contains the old history. If the team approves the rewrite, use --force-with-lease. It refuses to overwrite remote work that you have not fetched, making it safer than --force.

# Update a shared branch only after coordination
git push --force-with-lease origin feature/profile

Best Practices

  • Rebase a clean working tree and inspect the selected range first.
  • Keep a backup branch for complex history edits.
  • Write focused commits before using rebase as cleanup.
  • Run tests after rewriting and before pushing.
  • Avoid rewriting public commits unless collaborators agree.

Conclusion

Git interactive rebase gives you precise control over local commit history. Select the correct range, use the todo commands deliberately, resolve conflicts one commit at a time, and recover through the reflog when necessary. Careful use produces a clearer history without losing the work behind it.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram