git rebase
git rebase
: reapply commits from one branch on top of another branch.
The git rebase
command is used to move or combine a sequence of commits to a new base commit. Unlike git merge
, which creates a merge commit to combine two branches, rebasing takes the commits from your current branch and replays them on top of another branch, creating a linear commit history.
Rebasing is particularly useful for maintaining a clean, linear project history. Instead of creating a "commit salad" where commits from different branches are interleaved, rebasing ensures that your feature commits appear as if they were developed directly on top of the latest changes from the target branch.
There are two main types of rebasing:
-
Regular rebase: Takes all commits from your current branch and replays them on top of another branch, maintaining the same commit structure but with new base commits.
-
Interactive rebase (
git rebase -i
): Arguably the most powerful feature of Git, it allows you to interactively edit, reorder, squash, or drop commits during the rebase process.
Rebasing rewrites commit history by creating new commits with the same changes but different commit hashes. This means you should never rebase commits that have been shared with others, as it can cause confusion and conflicts for collaborators.
Pulling with rebase
By default, running git pull
is effectively a combination of git fetch
followed by git merge
. The merge step may create a useless merge commit in the current branch. Do it several times in the process of developing a feature, and you end up with a messy commit history, which will make the final merge especially tricky.
What you really want is to take the latest changes from the remote branch and put all of your recent commits on top of it. This can be achieved with git pull --rebase
. But adding that option every time is tedious, so you can set rebase on pull as the default behavior for your repository:
git config pull.rebase true
git merge
vs git rebase
Imagine you're making a sandwich (branch: feature/sandwich
) while your friend reorganizes the kitchen (branch: feature/kitchen-reorg
). Then you try to combine your work.
With git merge
:
HISTORY: YOU-THEM-THEM-YOU-⚠️-THEM-YOU-⚠️-THEM-YOU-⚠️-THEM-YOU-MERGE
With git rebase
:
HISTORY: THEM-THEM-THEM-THEM-⚠️-YOU-YOU-YOU-YOU
The key difference:
- Merge preserves the chaotic reality of parallel work with multiple conflicts.
- Rebase creates a clean timeline with one conflict resolution point, then smooth sailing.
Both end with the same result (sandwich + organized kitchen), but rebase tells a simpler story by pretending you started after the kitchen was already reorganized.
Examples
Rebase the current branch onto main
:
git rebase main
Start an interactive rebase for the last 3 commits:
git rebase -i HEAD~3
Continue a rebase after resolving conflicts:
git add .
git rebase --continue
Abort a rebase and return to the original state:
git rebase --abort
Update your current branch with the latest changes from main
(take the main
branch and put all of your commits on top of it):
git fetch origin
git rebase origin/main
Set rebase as the default behavior for git pull
:
git config pull.rebase true