Git rebase: apply your changes onto another branch

By on

Git’s rebase command reapplies your changes onto another branch. As opposed to merging, which pulls the differences from the other branch into yours, rebasing switches your branch’s base to the other branch’s position and walks through your commits one by one to apply them again.

Let’s look at an example. While working on a branch named login, based on the main branch, one of your team members pushed some changes to main. You need these changes to finish the login feature in your branch.

branch.svg

Figure 1: The new commits in the main branch (E and F), are needed to finish work in the login branch.

Rebase vs merge

Merging the main branch back into yours would result in a merge commit, which includes the changes between both branches and exists to show where a merge occurred.

Merging a branch is useful when the moment of merging is significant. For example, when a feature is merged into the main branch, or when a new release is pushed.

When working on a branch with multiple people, merging is preferable to rebasing as it leaves the branch history intact.

merge.svg

Figure 2: Merging the two branches results in a merge commit.

In this case, it’s not important to know when main was merged in, and there is nobody else working on the login branch. Instead of merging the main branch in, rebasing it rewrites history to make sure all commits on the login branch are based on the current state of the main branch.

rebase.svg

Figure 3: Rebasing applies the commits from the login branch on top of the main branch.

Git’s rebase command temporarily rewinds the commits on your current branch, pulls in the commits from the other branch and reapplies the rewinded commits back on top. This bases the current branch onto the other branch.

$ git rebase main
First, rewinding head to replay your work on top of it...
Fast-forwarded login to main.

It’s as if you didn’t start working in the login branch before the commits you pulled in were made1.

Conflicts served in smaller chunks

Unlike a merge, which merges two branches in one go, rebasing applies the changes from one branch one by one. Because of that, conflicts will be served in smaller chunks making them easier to fix and understand:

$ git rebase main
First, rewinding head to replay your work on top of it...
Applying: login
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging config/environment.rb
CONFLICT (content): Merge conflict in config/environment.rb
Failed to merge in the changes.
Patch failed at 0001 login

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

When you’re done fixing a conflict, simply git add the file and continue rebasing:

$ git rebase --continue

1

Alternatively, pull with rebase to prevent having to switch out of the current branch.