Rebasing
Learn how to rebase your Git branches effectively.
Git rebase is one of Git's most powerful features, allowing you to rewrite commit history. Its primary purpose is to integrate changes from one branch into another by moving or combining a sequence of commits to a new base commit.
This guide will walk you through how to use git rebase
, from basic scenarios to more advanced interactive rebasing.
Why Rebase?
The main reason to use git rebase
is to maintain a clean and linear project history.
- Cleaner History: Unlike
git merge
, which creates a merge commit every time you integrate changes,rebase
rewrites history to appear as if you created your branch from the latest commit on the target branch. This results in a straight-line history that is often easier to read and navigate. - Tidying Commits: Before you merge a feature branch, you can use interactive rebase to clean up your commit history. This includes squashing multiple small commits into one, rewording commit messages, and reordering commits to create a logical sequence of changes.
Standard Rebase
A standard rebase takes the commits from your current branch and reapplies them on top of another branch.
Scenario: Updating a Feature Branch
Imagine you started a feature branch my-feature
from main
. While you were working, other developers pushed updates to main
. To incorporate these updates into your branch, you can rebase my-feature
onto main
.
-
First, ensure your
main
branch is up-to-date:git checkout main git pull origin main
-
Switch back to your feature branch and rebase it onto
main
:git checkout my-feature git rebase main
Git will now move the entire my-feature
branch to begin on the tip of the main
branch, reapplying your commits one by one.
Interactive Rebase (-i
)
Interactive rebase gives you fine-grained control over your branch's commit history. It's incredibly useful for cleaning up your work before sharing it.
To start an interactive rebase, use the -i
flag. For example, to rebase the last 3 commits on your current branch:
git rebase -i HEAD~3
This command opens an editor with a list of the commits you're about to rebase, along with instructions.
pick 1a2b3c4 Add feature X
pick 5d6e7f8 Fix bug in feature X
pick 9g8h7i6 Add tests for feature X
# Rebase 1234567..9g8h7i6 onto 1234567 (3 commands)
#
# 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
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to re-create the commit's
# . author and time.
#
# These lines can be re-ordered; they are executed from top to bottom.
You can change pick
to any of the commands listed. For example, to combine all three commits into one:
pick 1a2b3c4 Add feature X
squash 5d6e7f8 Fix bug in feature X
squash 9g8h7i6 Add tests for feature X
After saving and closing the editor, Git will combine the commits and prompt you to write a new commit message for the single, combined commit.
Resolving Conflicts
Conflicts can occur during a rebase if one of your commits modifies the same part of a file as a commit in the target branch. When a conflict happens, the rebase process will pause.
- Git will tell you which file has a conflict. Open the file and resolve the conflict markers (
<<<<<<<
,=======
,>>>>>>>
). - After resolving the conflict, stage the modified file:
git add <conflicted-file>
- Continue the rebase:
git rebase --continue
If you get stuck or want to cancel the rebase, you can always abort:
git rebase --abort
The Golden Rule of Rebasing
Never rebase a public branch that other developers have based their work on.
Rebasing rewrites commit history. If you rebase a branch like main
or a shared feature branch, you are creating new commits. When other developers pull the rebased branch, Git will see their local history as having diverged from the remote, leading to confusion and complicated merges.
Only rebase branches that are local to your machine and that you haven't shared with others.
Pulling with Rebase
When you use git pull
, it defaults to fetching and then merging (git fetch
+ git merge
). This can clutter your history with merge commits. To maintain a linear history, you can configure pull
to use rebase instead:
git pull --rebase
This command fetches the remote changes and then rebases your local commits on top of the updated remote branch.
You can make this the default behavior for all branches:
git config --global pull.rebase true