When you work on a feature branch for a few days, main usually moves on without you. To bring those new commits into your branch, you've learned to merge, which joins the two histories with a merge commit. Git offers a second way to combine work: rebase.
Rebasing takes the commits on your branch and replays them, one by one, on top of the latest main, as if you'd started your work from there. The result is a straight, linear history with no merge commits, which many teams find easier to read and review.
Rebase is powerful, and it rewrites history, which brings one very important rule. In this lesson you'll rebase a branch, compare the result with merging, resolve conflicts during a rebase, use git pull --rebase, tidy your commits with interactive rebase, and learn the golden rule that keeps teammates safe.
What rebase does
Imagine main has commits A, B and C, and your branch feature started at B and added commits X and Y. Meanwhile, C was added to main.
git switch feature
git rebase mainGit sets X and Y aside, moves feature to the tip of main (C), then re-applies X and Y on top. The re-applied commits have the same changes and messages but new hashes, because their parent changed. Afterwards, feature contains A, B, C, X', Y' in a straight line, and merging it into main is a simple fast-forward.
Rebase or merge?
| Merge | Rebase | |
|---|---|---|
| History | Shows exactly what happened, including when branches joined | A clean, straight line |
| Extra commits | A merge commit | None |
| Rewrites commits | No | Yes, gives commits new hashes |
| Safe on shared branches | Yes | No, only on your own local or private branches |
Both are correct tools. A common team habit is: rebase your own feature branch onto main to stay up to date, then merge it into main through a pull request.
Conflicts during a rebase
Because commits are replayed one at a time, a conflict pauses the rebase at the commit that caused it:
- Open the conflicted files, fix them and remove the markers, just as in the merge lesson.
git addthe fixed files.git rebase --continueto move on to the next commit.
git rebase --skip drops the current commit, and git rebase --abort cancels everything and returns your branch to how it was before the rebase. You can always abort if things get confusing.
Interactive rebase
git rebase -i HEAD~3 opens a list of your last three commits in your editor, oldest first, each with a command word:
pick a1b2c3d Add search box
pick d4e5f6a Fix typo
pick 9f8e7d6 Fix another typoChange the words to rewrite history before sharing it:
- pick: keep the commit as it is.
- reword: keep it but change its message.
- squash or fixup: combine it into the commit above (squash keeps both messages, fixup discards this one's).
- drop: remove the commit entirely.
Save and close, and Git rebuilds the commits as instructed. It's the standard way to turn a messy series of "WIP" commits into a few clean ones before opening a pull request.
Git Rebase Syntax
Rebase commands
git switch feature
git rebase main
git rebase --continue
git rebase --abort
git pull --rebase
git rebase -i HEAD~3
git push --force-with-lease # after rebasing your own pushed branchGit Rebase Summary
git rebase mainreplays your branch's commits on top of main, giving them new hashes.- Rebase gives a linear history; merge preserves the exact history with merge commits.
- Resolve rebase conflicts,
git add, thengit rebase --continue;--abortcancels. git rebase -ilets you reword, squash, fixup and drop commits.- Only rebase commits that haven't been shared with others.
Git Rebase Examples
Each example shows the code, the output it produces and what each part does.
Updating a feature branch with rebase
git log --oneline --graph --all
git switch search-box
git rebase main
git log --oneline --graph --all* 7e1c0d2 (main) Fix footer link
| * 4b9a8c3 (HEAD -> search-box) Style search box
| * 2d6f1e4 Add search box
|/
* 9d41e07 Add contact form
Successfully rebased and updated refs/heads/search-box.
* 8a3b2f7 (HEAD -> search-box) Style search box
* 5c1e9d0 Add search box
* 7e1c0d2 (main) Fix footer link
* 9d41e07 Add contact formLine-by-line explanation
- Line 1Before: main gained "Fix footer link" after search-box branched off.
- Line 3Replay the two search-box commits on top of main.
- Line 4After: one straight line. The commits have new hashes because their parent changed.
Pulling with rebase instead of merge
git status
git pull --rebase
git log --oneline -3On branch main
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
Successfully rebased and updated refs/heads/main.
c3d9e8f (HEAD -> main) Add FAQ section
b38e0f5 (origin/main) Update README with screenshots
9d41e07 Add contact formLine-by-line explanation
- Line 1Your main and the remote main each have a commit the other doesn't.
- Line 2Instead of creating a merge commit, your local commit is replayed on top of the remote one.
- Line 3The history stays linear, and your commit is now ready to push normally.
Squashing commits before a pull request
The editor opened by git rebase -i HEAD~3 was changed to this, then saved.
pick 2d6f1e4 Add search box
fixup 6a7b8c9 Fix typo in placeholder
fixup 3e4f5a6 Fix typo againSuccessfully rebased and updated refs/heads/search-box.
$ git log --oneline -1
1f2e3d4 (HEAD -> search-box) Add search boxLine-by-line explanation
- Line 1Keep the main commit.
- Lines 2 to 3fixup folds both typo fixes into it and discards their messages.
Common Git Rebase Mistakes
Rebasing a shared branch
git switch main
git rebase feature
git push --force # rewrites main for everyonegit switch main
git merge feature
git pushForgetting to continue after fixing a conflict
# conflict fixed and files saved...
git commit -m "Fix conflict" # creates an extra commit mid-rebasegit add styles.css
git rebase --continueUsing --force instead of --force-with-lease
git push --forcegit push --force-with-leaseAfter rebasing your own pushed branch, --force-with-lease refuses to overwrite commits someone else added.
Git Rebase in Real Projects
Rebase in professional teams
Many teams ask contributors to rebase their pull requests on the latest main and squash fix-up commits before review, which keeps history readable. Large open-source projects such as the Linux kernel rely heavily on rebasing patch series, and GitHub's "Rebase and merge" button applies the same idea when merging a pull request.
Git Rebase FAQ
How do I undo a rebase after it has finished?
Git saves your branch's previous position in ORIG_HEAD, so git reset --hard ORIG_HEAD straight after the rebase puts it back. If you've run other commands since, find the entry from before the rebase in git reflog and reset to that instead. Commit or stash any uncommitted work first, because --hard discards it.
How do I squash my last three commits into one?
Run git rebase -i HEAD~3, keep pick on the first line and change the other two to squash (or fixup to drop their messages). Save, edit the combined message, and you have one commit. A quick alternative is git reset --soft HEAD~3 followed by git commit.
What does git pull --rebase do?
It fetches from the remote and then rebases your local commits on top of what it downloaded, instead of creating a merge commit. Your history stays a straight line. You can make it the default with git config --global pull.rebase true.
What does git rebase --onto do?
It moves a range of commits onto a different base. git rebase --onto main old-base feature takes the commits on feature that come after old-base and replays them on top of main. It's useful when you branched from another feature branch and now want your work based on main alone.
What is a fixup commit?
git commit --fixup=3f9c2ab makes a commit whose message starts with fixup! and names the commit it corrects. Later, git rebase -i --autosquash main moves it next to that commit and merges them automatically. It's a tidy way to fix an earlier commit on your branch before opening a pull request.
Git Rebase Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the commands that replay your feature branch onto main.
git switch feature
git main
What happens to the hashes of rebased commits?
After fixing a conflict during a rebase, what do you run?
In an interactive rebase, a commit is marked fixup. What happens to it?
What does the golden rule of rebasing say?
Git Rebase Quiz
5 questions to check what you learned.
What does rebasing produce compared with merging?
- More merge commits
- A deleted branch
- A linear history without merge commits
- A new remote
How do you cancel a rebase that's going badly?
- git rebase --stop
- git rebase --abort
- git reset --rebase
- Delete the .git folder
What does
git pull --rebasedo?- Fetches, then replays your local commits on top of the remote branch
- Merges the remote with a merge commit
- Rebases the remote onto your branch
- Deletes local commits
Which interactive rebase command changes only a commit's message?
- pick
- drop
- squash
- reword
Why push with --force-with-lease after rebasing your own branch?
- It's faster than a normal push
- Normal push is disabled after a rebase
- The remote has your old commits, and --force-with-lease only overwrites them if nobody else has pushed since
- It creates a backup branch