Git Rebase



There are two primary approaches in Git for incorporating changes from one branch into another: merging and rebasing.

By generating a merge commit that contains the most recent snapshots of both branches (C3 and C4 as seen in the following image) as well as their common ancestor (C2), merging integrates the modifications from two branches.

This method adds a merge commit but keeps the branch history intact.

git merge 1

Alternatively, by replaying the modifications on top of another branch (C3), rebasing enables us to apply the patch introduced in a commit (C4).

Rebasing is the process of applying commits from one branch right on top of another to create a linear history, usually without generating a merge commit.

As seen in the following image let's say we have a feature branch (feature) that branched off from the main branch. While you're working on feature, changes are made to the main branch by other team members. Instead of merging main into your feature and creating a merge commit, you can rebase your branch on top of main. This process reapplies your commits as if they were made after the latest changes in main, keeping the history clean and linear.

git merge 2
$ git checkout feature
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

How Rebase Works

The git rebase command when executed, Git performs the following steps:

  • Identify the base: Git finds the common ancestor between the current branch and the branch we're rebasing onto.

  • Temporarily save your commits: Git saves the changes and temporarily removes the commits from the current branch.

  • Apply changes from the target branch: Git updates the branch to match the state of the branch we are rebasing onto.

  • Reapply your commits: Git applies the commits one by one on top of the new base (i.e., the target branch).

  • Update branch pointer: Git updates the pointer for the branch to the new state with the rebased commits.

Let's take a look at the following example, here let's say feature branch has commit `C4` and main has commit `C3` commit. When we rebase feature onto main, Git will rewrite the history so that our branch now appears as if `C4` was made on top of `C3`.

git merge 3

For this example, we would switch to the feature branch and then rebase it on the master branch like this:

$ git checkout feature
$ git rebase main

Benefits of Using Rebase

Following are some of the benefits of rebasing:

  • Cleaner History: Rebase creates a clean, linear history, making it easier to follow the flow of changes. Instead of having merge commits that might clutter the history, you only see a straight line of commits.

  • Easy to Read: When working with a large team, a history with multiple branches and merge commits can get hard to understand. Rebasing simplifies this by eliminating unnecessary merge commits.

  • Better Context: Rebasing allows you to put your changes in the context of the latest code on the main branch, which can make it easier to spot integration issues early.

The Risks of Rebasing in Git

In Git, rebasing can be a very useful tool to maintain a neat and orderly commit history.

  • Do Not Rebase Public History:One of the most important rules when using Git rebase is to never rebase commits that have been shared with others. Once you've pushed commits to a remote repository (like GitHub), rebasing them can cause issues for others working on the same branch. Instead, use rebase for your local branches and feature branches that have not yet been shared.

  • Conflict Resolution: Rebasing can often lead to conflicts when Git tries to apply the changes on top of the new base commits. When a conflict occurs, Git will pause the rebase process and allow users to resolve the conflict manually. After resolving the conflicts, user can continue the rebase process using:

    git rebase --continue
    

    If user wants to abort the rebase process and return the branch to its original state, use:

    git rebase --abort
    

Rebase Best Practices

  • Use Rebase for Local Cleanup: Rebase is a great tool for cleaning up local commits before pushing them to a shared repository. This ensures that the commit history remains tidy.

  • Interactive Rebase for Commit Polishing: Use interactive rebase to combine, reorder, or edit commits. This allows users to present a clean and logical commit history when contributing to shared branches.

  • Avoid Rebasing Shared Branches: Do not rebase commits that have already been pushed to a shared branch, as this can cause confusion and conflicts for other developers.

  • Use Rebase for Feature Branches: When working on a feature branch, use rebase to keep the changes up-to-date with the main branch, especially before merging it into the main branch.

  • Practice on a Test Branch: Before performing a complex rebase operation, practice on a test branch or use Gits reflog to recover in case of mistakes.

Advertisements