Rewriting Git History | git rebase
The git rebase command
Rebasing moves the base commit of a branch to another commit. The general behavior is shown in the tutorial diagram.
Git Tutorial: Keeping project history linear with rebase
On the surface, rebase looks like a way to move a branch from one commit to another. Internally, however, Git creates new commits and applies them onto the target base commit. That means it is rewriting project history. It is important to understand that even if the branch appears to be the same, the commits that make it up are different.
Usage
git rebase <base>
Rebases the current branch onto <base>. Any kind of commit reference can be used as the rebase target, including a commit ID, branch, tag, or relative reference from HEAD.
Additional notes
The main purpose of rebase is to keep project history linear. For example, consider a scenario where master moves forward after you start working on a feature.
There are two ways to integrate the feature into master: merge it directly, or rebase it and then merge it. The first option requires a three-way merge and a merge commit. The second option allows a fast-forward merge and keeps the history perfectly linear. The tutorial diagram explains why the rebased version can be fast-forwarded into master.
Git Tutorial: Fast-forward merge
Rebase is a common way to integrate upstream changes into a local repository. If you use git merge to bring in upstream changes, an unnecessary merge commit may be created every time you check project progress. Rebase instead means, “I want all of my work to be based on the latest completed changes.”
Do not rebase public commits
As explained for git commit --amend and git reset, do not rebase commits that have already been pushed to a public repository. Rebase replaces old commits with new commits, which can make part of the project history appear to be missing.
Example
The following example combines git rebase and git merge to keep project history linear. It is a simple way to guarantee a fast-forward merge.
# Start a new feature
git checkout -b new-feature master
# Edit files
git commit -a -m "Start developing a feature"
Suppose a security vulnerability is discovered in the codebase while the feature is being developed.
# 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 the hotfix is merged into master, the project history has diverged. Instead of simply running git merge, rebase the feature branch so it can be integrated while keeping the history linear:
git checkout new-feature
git rebase master
Now new-feature has moved to the tip of master, so it can be merged with a normal fast-forward merge:
git checkout master
git merge new-feature