Git Rebase: A Guide to Rebasing Branch Commits
Git rebase is a powerful command that enables developers to adjust commit history, apply changes from one branch to another, and maintain a tidy, linear project timeline. This article describes how to rebase branch commits in Git.
The Short Answer Version
If you are already familiar with Git and need a quick reference for rebasing commands, here are the essentials:
# Reapply your branch commits on top of the latest main
$ git switch feature ## Switch to your feature branch
$ git rebase main ## Rebase commits onto the main branch
# Interactively rebase the last 3 commits (edit, squash, reorder)
$ git rebase -i HEAD~3
# Rebase local commits while pulling remote changes (cleaner history)
$ git pull --rebase origin main
# After rebase, push rewritten history to remote
$ git push --force-with-lease ## Safer than --force
Understanding Git Rebase
Rebasing transfers commits from a source branch and reapplies them on top of a target branch. This results in a streamlined commit history without additional merge commits. While the commits remain functionally the same, their IDs change, because Git creates new commits based on the old ones.
Command Syntax
git rebase [OPTIONS] [UPSTREAM [BRANCH]]
- [OPTIONS]: Define how the command behaves. Covered later in this article.
- UPSTREAM: The branch onto which commits will be reapplied.
- [BRANCH]: The branch whose commits are being rebased. Defaults to the current branch if omitted.
Command Usage
Switch to the branch you want to rebase:
$ git switch feature-branch
Reapply your feature branch commits on top of main:
$ git rebase main
Clean up commits interactively before rebasing:
$ git rebase -i
Push your branch (if it has never been pushed before):
$ git push
If you have already pushed the branch before rebasing, use force push (as the history has changed):
$ git push --force-with-lease
Note: Using --force-with-lease
instead of --force
ensures you don’t overwrite others’ work on the branch.
Git Rebase vs Git Merge
git rebase
rewrites commit history by moving commits between branches. git merge
, in contrast, generates a new commit that merges the changes of two branches, keeping history intact without modifying commit positions.
Choose merging for shared branches, and rebasing for cleaning local or feature branch history before merging.
When to Use Rebase
- When you want a simpler, linear history.
- When you want to avoid unnecessary merge commits.
- When you need to reapply changes on top of the latest main branch before pushing.
Git Merge
Git Merge integrates changes from one branch into another, creating a merge commit that preserves the histories of both branches. This allows a clear record of how development progressed.
Switch to your main branch:
$ git switch main
Merge the feature branch into main, creating a merge commit if required:
$ git merge feature-branch
Types of Git Rebase
Interactive Rebase
Interactive rebasing enables you to edit, remove, squash, or reorder commits. It’s perfect for cleaning messy commit histories before pushing to a shared repository.
Start an interactive rebase of the last three commits:
$ git rebase -i HEAD~3
You’ll see a list like this in your editor:
pick a1b2c3d Add login functionality
pick b2c3d4e Fix login bug
pick c3d4e5f Update login style
You can replace pick
with:
- reword: Modify commit message
- edit: Adjust the commit
- squash: Combine with previous commit
- drop: Remove the commit
Non-Interactive Rebase
This default mode replays commits on top of another branch in the same order, without allowing interactive edits. Useful for keeping a feature branch updated with the base branch.
Rebase commits on top of main:
$ git rebase main
Auto-Merge Rebase
When using --autostash
, Git automatically stashes local changes before rebasing and reapplies them afterward, preventing errors from uncommitted changes.
Stash local changes, rebase onto main, and reapply stashed changes after rebase:
$ git rebase main --autostash
Common Configuration Options
Below are the frequently used configuration options for git rebase
:
- –interactive (-i): Opens an editor to manually adjust, reorder, squash, or remove commits during the rebase process.
- –skip: Skips the current commit (usually one that triggered a conflict) and continues the rebase.
- –continue: Proceeds with the rebase after conflicts are resolved and changes are staged.
- –abort: Stops the rebase and resets the branch to its original state before the rebase began.
- –autostash: Automatically stashes any uncommitted local changes before rebasing and reapplies them afterward.
- –onto <newbase>: Rebases a range of commits onto a new base commit, typically used in advanced scenarios.
Conclusion
In this article, you explored how to rebase Git commits using both interactive and non-interactive methods, while also understanding the distinction between rebase and merge. By applying these techniques, you can maintain a cleaner commit history, reduce unnecessary merge commits, and improve collaboration workflows. For further details, consult the official Git documentation.