Git Rebase is not nearly as complicated as it sounds — or as confusing as the documentation or other explanations make it out to be. It’s a powerful tool that’ll make your git history easier to follow.
What is Git Rebasing?
git rebase
is the process of moving or combining a sequence of commits to a new base commit. Rebasing changes the base of your branch from one commit to another making it appear as if you’d created your branch from a different commit.
Git accomplishes this by creating new commits and applying them to the specified base. It’s very important to understand that even though the branch looks the same, it’s composed of entirely new commits.
Git Rebasing vs. Merging
The first thing to understand about git rebase
is that it solves the same problem as git merge
Both are designed to integrate changes from one branch into another — just in different ways.
- When you do rebase a feature branch onto master, you move the base of the feature branch to master branch’s ending point.
- Merging takes the contents of the feature branch and integrates it with the master branch. As a result, only the master branch is changed. The feature branch history remains same.
- Merging adds a new commit to your history.
There’s also a special kind of merge called fast-forward, done when a branch being merged is just a continuation of the branch you’re merging into—so the new commits are just pasted on top of the target branch (ie. it is “fast-forwarded”).
Let’s say you start working on a new feature in a dedicated branch, then another developer updates the master
branch with new commits resulting in a forked history.
The new commits in master
are needed to the feature you’re working on so needs to be incorporated into your feature
branch — there’s two options, merge or rebase.
Option 1 — Merge the Branch
The simplest option would be to merge the master
branch into the feature branch using git merge
:
git checkout feature
git merge master
or as a one-liner:
git merge feature master
This will create a new “merge commit” in the feature
branch that ties the histories of both branches which looks like this:
This option is non-destructive, the existing branches are not changed in any way which avoids all the potential pitfalls of rebasing (see below).
Option 2 — Rebase the Branch
The other option is to rebase the feature
branch onto the master
branch:
git checkout feature
git rebase master
This operation moves the entire feature
branch to begin on the tip of the master
branch which incorporates all new commits in master
. Instead of merging, git rebasing re-writes the project history by creating brand new commits for each commit in the original branch.
Benefits to Rebasing — two trade-offs.
- Streamlines a potentially complex history
- Avoids merge commit “noise” in busy repos with busy branches
- Cleans intermediate commits by making them a single commit
The major benefit to git rebasing is a much cleaner project history. It eliminates unnecessary merge commits required by git merge
and results in a perfectly linear project history — shown in the diagram above. You’ll be able to follow the top of feature
all the way to the beginning of the project with git log
, git bisect
and gitk
.
The two-trade offs are safety & traceability. If you don’t follow the golden rule of rebasing, never use it on public
branches, re-writing project history can be catastrophic for collaboration. Rebasing loses the context provided by a merge commit so unable to see when upstream changes were incorporated into the feature.
How to Git Rebase
git rebase [base]
The Git command above will rebase the current branch onto [base], which can be any kind of commit reference (an ID, a branch name, a tag, or a relative reference to HEAD
). When ran, Git performs the following steps:
- Identifies each commit that is an ancestor of the current commit but not of [base]. This can be thought of as a two-step process: first, find the common ancestor of [base] and the current commit; call this the ancestor commit. Second, collect all the commits between the ancestor commit and the current commit.
- Determines what changed for each of those commits, and puts those changes aside.
- Sets the current head to point to [base].
- For each of the changes set aside, replays that change onto the current head and creates a new commit.
Once completed, HEAD
(the current commit), is a descendant of [base], but it contains all the changes as if it had been merged with [base].
Git Rebase — behind the scenes.
Let’s take 2 branches for example:
- Branch
you
: the branch you are rebasing - Branch
johnny
: the branch from which you get the new commits
Johnny made some commits and you want to pull those into your branch while keeping the commits and history clean. To do so:
git checkout you
git rebase johnny

When you rebase you
on johnny
, git creates a temporary branch that is a copy of branch johnny
, and tries to apply the new commits of you
on it one by one.
For each commit to apply, if there are conflicts, they will be resolved inside of the commit.
After a rebase, the new commits from you
(in blue) are not exactly the same as they were:
- If there were conflicts, those conflicts are integrated in each commit
- They have a new hash
But they keep their original date which might be confusing since in the final branch, commits in blue were created before the two last commits in purple.
Git Rebase Golden Rule
Never rebase while you’re on a public branch — only rebase a branch if you are the only one using it.
Rebase has the advantage that there is no merge commit created, but HEAD
is not a descendant of the pre-rebase HEAD
commit which means rebasing can be problematic.
This means that a rebased head cannot be pushed to a remote server, because it does not result in a fast-forward merge. Moreover, it results in a loss of information. It is no longer known that the branch your rebasing was once on its current HEAD
. This changes history
and could confuse someone who already knows about the commit.
When should you rebase vs. merge?
- Use merge in cases where you want a set of commits to be clearly grouped together in history
- Use rebase when you want to keep a linear commit history
- Don’t use rebase on a public/shared branch
If the feature branch you are getting changes from is shared with other developers, rebasing is not recommended, because the rebasing process will create inconsistent repositories. For individuals, rebasing makes a lot of sense.
If you want to see the history completely same as it happened, you should use merge. Merge preserves history whereas rebase rewrites it.
Rebasing is better to streamline a complex history, you are able to change the commit history by interactive rebase. You can remove undesired commits, squash two or more commits into one or edit the commit message.
Rebase will present conflicts one commit at a time whereas merge will present them all at once. It is better and much easier to handle the conflicts but you shouldn’t forget that reverting a rebase is much more difficult than reverting a merge if there are many conflicts.
Here’s some examples of when you should use git rebase
:
Situation 1: You’re using a private branch.
By public branches
are branches that other people might have checked out. If you’re developing a branch on your own and not sharing it with anyone, you could rebase it to keep the branch up to date with respect to the main branch. Then, when you finally merge your developed branch into the main branch, it will be free of merge commits, because it will appear that your development branch was a descendant of the main head. Moreover, the main branch can move forward with a fast-forward merge rather than a regular merge commit.
Rebasing rewrites history, and anyone having branches that were checked out of the history you just unmade will be sad, angry or worse. That’s one reason you can’t just push rebased branch on GitHub (unless you force it and sacrifice a kitten). So just say no.
Rebasing private branches is perfectly fine, and in fact often done when squashing or rearranging commits, cleaning up a branch before going public with it, or just updating long-running feature branch (go easy on the last one, though).
Situation 2: A remote branch changes at the same time.
If you commit to a branch, but that branch changes at the same time on a remote machine, you can use rebase to shift your own commits, allowing you to push your commits to the remote repository.
Git Rebasing Examples
The example below combines git rebase with git merge to maintain a linear project history. This is a quick and easy way to ensure that your merges will be fast-forwarded.
# Start a new feature
git checkout -b new-feature master
# Edit files
git commit -a -m "Start developing a feature"
In the middle of our feature, we realize there’s a security hole in our project:
# Create a hotfix branch based off of master
git checkout -b hotfix master
# Edit files
git commit -a -m "Fix security hole"
# Merge back into master
git checkout master
git merge hotfix
git branch -d hotfix
After merging the hotfix into master, we have a forked project history. Instead of a plain git merge, we’ll integrate the feature branch with a rebase to maintain a linear history:
git checkout new-feature
git rebase master
This moves new-feature to the tip of master, which lets us do a standard fast-forward merge from master:
git checkout master
git merge new-feature
3 comments on “Git Rebase”.
# Apr 29, 2021
if I’m collaborator with my team , you should be never change my history (if i use git pull), you must git me update not delete my history from my pc
so , don’t use rebase with your team or extern people
# Oct 22, 2019
Rule One: Never Rebase Public Branches
It means that you shouldn’t do this rebase command while beeing on master branch.
# Aug 18, 2017
Can you please give example with step by step picture regarding Rule One: Never Rebase Public Branches, I don’t get it.
Maybe in real example of Centralized Workflow for 2/3 Developer.
All comments posted on 'Git Rebase' are held for moderation and only published when on topic and not rude. Get a gold star if you actually read & follow these rules.
You may write comments in Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (```) with double new lines before and after.
Want to tell me something privately, like pointing out a typo or stuff like that? Contact Me.