git rebase takes the changes from one branch and applies them onto another branch, effectively moving the base of the branch to a new starting point. This helps to create a linear and clean project history.

Example: If feature branch A was created at commit-11 and the main branch has since added 3 more commits, rebasing feature branch A will make it look like it was created at commit-14.

Git Rebase vs Git Pull

git pull fetches changes from a remote branch and merges them into your current branch. By default, it performs a merge operation, which may create a merge commit if there are conflicts or differences between the branches.

AspectGit RebaseGit Pull (with Merge)
ActionReplays commits from one branch onto another, creating a linear history.Fetches changes from a remote branch and merges them into the current branch.
Use WhenYou want a clean, linear commit history.You need to preserve the historical context of changes.
ProsCleaner history, easier to follow. (For clean, linear history on private/feature branches.)Maintains commit history, easier to track changes in collaborative environments.

Git Rebase Steps

  1. Checkout to your current branch: Ensure you’re on the feature branch you want to update.
    git checkout your-feature-branch
  2. Ensure your working directory is clean: Make sure you have committed or stashed any changes in your current branch.
  3. Fetch the latest changes from the remote: This ensures you have the latest updates.
    git fetch origin
  4. Rebase your branch with develop: This applies the changes from develop onto your current branch.
    git rebase origin/develop
  5. Resolve any conflicts: If there are conflicts, Git will stop and allow you to resolve them. After resolving the conflicts, continue the rebase process (similar to merge).
    git add <file-with-conflict>
    git rebase --continue
  6. Push (or force push) to update the remote feature branch: If your feature branch already has some commits that are conflicting with main’s history, you may need to force push the rebased branch (to rewrite the history). To avoid this, rebase every time you push.
    git push origin your-feature-branch
    or
    git push origin your-branch --force

Git Pull Rebase

We can skip steps 3 and 4 from the above steps by using git pull --rebase instead of git fetch origin and git rebase.

Steps 3 and 4 can be replaced by this command:

git pull origin develop --rebase

This will:

  1. Fetch the latest commits from the remote develop branch.
  2. Rebase your local branch on top of the updated develop branch.

Git Rebase Commits Visualization

In both feature branches, rebasing was not done before each push. This causes conflicts with the timelines during rebase and requires a force push. The force push will change the commit times to just after the rebase, resulting in the loss of the original commit times of feature branches.

Before Rebase

    gitGraph
        commit id: "Initial Commit"
        commit id: "mb:c-1"
        commit id: "mb:c-2"
        branch feature_branch
        branch feature_branch_2
        checkout feature_branch
        commit id: "fb:c-1"
        checkout feature_branch_2
        commit id: "fb2:c-1"
        checkout main
        commit id: "mb:c-3"
        commit id: "mb:c-4(conf fb2:c1)"
        checkout feature_branch
        commit id: "fb:c-2"
        checkout feature_branch_2
        commit id: "fb2:c-2"
        checkout main
        commit id: "mb:c-5"
        checkout feature_branch
        commit id: "fb:c-3"
        commit id: "fb:c-4"
        checkout feature_branch_2
        commit id: "fb2:c-3"

After Rebase

    gitGraph
        commit id: "Initial Commit"
        commit id: "mb:c-1"
        commit id: "mb:c-2"
        checkout main
        commit id: "mb:c-3"
        commit id: "mb:c-4(conf fb2:c1)"
        commit id: "mb:c-5"
        branch feature_branch
        branch feature_branch_2
        checkout feature_branch
        commit id: "fb:c-1"
        checkout feature_branch_2
        commit id: "fb2:c-1"
        checkout feature_branch
        commit id: "fb:c-2"
        checkout feature_branch_2
        commit id: "fb2:c-2"
        checkout feature_branch
        commit id: "fb:c-3"
        commit id: "fb:c-4"
        checkout feature_branch_2
        commit id: "fb2:c-3"