Rebase and resolve merge conflicts

In Git, a rebase updates your branch with the contents of another branch. A rebase confirms that changes in your branch don’t conflict with changes in the target branch.

If you have a merge conflict, you can rebase to fix it.

When you rebase:

  1. Git imports all the commits submitted to your target branch after you initially created your branch from it.
  2. Git applies the commits from your branch on top of the imported commits:

    Git rebase illustration

While most rebases are performed against main, you can rebase against any other branch. You can also specify a different remote repository. For example, upstream instead of origin.

caution
git rebase rewrites the commit history. It can cause conflicts in shared branches and complex merge conflicts. Instead of rebasing your branch against the default branch, consider using git pull origin master. Pulling has similar effects with less risk of compromising others’ work.

Rebase

When you use Git to rebase, each commit is applied to your branch. When merge conflicts occur, you are prompted to address them.

For more advanced options for your commits, use an interactive rebase.

Prerequisites:

To use Git to rebase your branch against the target branch:

  1. Open a terminal and change to your project directory.
  2. Ensure you have the latest contents of the target branch. In this example, the target branch is main:

    git fetch origin main
    
  3. Check out your branch:

    git checkout my-branch
    
  4. Optional. Create a backup of your branch:

    git branch my-branch-backup
    

    Changes added to my-branch after this point are lost if you restore from the backup branch.

  5. Rebase against the main branch:

    git rebase origin/main
    
  6. If merge conflicts exist:
    1. Resolve the conflicts in your editor.

    2. Stage the changes:

      git add .
      
    3. Continue the rebase:

      git rebase --continue
      
  7. Force push your changes to the target branch, while protecting others’ commits:

    git push origin my-branch --force-with-lease
    

Interactive rebase

Use an interactive rebase to specify how to handle each commit. The following instructions use the Vim text editor to edit commits.

To rebase interactively:

  1. Open a terminal and change to your project directory.
  2. Ensure you have the latest contents of the target branch. In this example, the target branch is main:

    git fetch origin main
    
  3. Check out your branch:

    git checkout my-branch
    
  4. Optional. Create a backup of your branch:

    git branch my-branch-backup
    

    Changes added to my-branch after this point are lost if you restore from the backup branch.

  5. In the GitLab UI, in your merge request, confirm the number of commits to rebase in the Commits tab.
  6. Open these commits. For example, to edit the last five commits:

    git rebase -i HEAD~5
    

    Git opens the commits in your terminal text editor, oldest first. Each commit shows the action to take, the SHA, and the commit title. For example:

    pick 111111111111 Second round of structural revisions
    pick 222222222222 Update inbound link to this changed page
    pick 333333333333 Shifts from H4 to H3
    pick 444444444444 Adds revisions from editorial
    pick 555555555555 Revisions continue to build the concept part out
    
    # Rebase 111111111111..222222222222 onto zzzzzzzzzzzz (5 commands)
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    # e, edit <commit> = use commit, but stop for amending
    # s, squash <commit> = use commit, but meld into previous commit
    # f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
    
  7. Switch to Vim’s edit mode by pressing i.
  8. Use the arrow keys to move the cursor to the commit you want to edit.
  9. For each commit, except the first one, change pick to squash or fixup (or s or f).
  10. Repeat for the remaining commits.
  11. End edit mode, save, and quit:

    • Press ESC.
    • Type :wq.
  12. When squashing, Git prompts you to edit the commit message:

    • Lines starting with # are ignored and not included in the commit message.
    • To keep the current message, type :wq.
    • To edit the commit message, switch to edit mode, make changes, and save.
  13. Push your changes to the target branch.

    • If you didn’t push your commits to the target branch before rebasing:

      git push origin my-branch
      
    • If you already pushed the commits:

      git push origin my-branch --force-with-lease
      

      Some actions require a force push to make changes to the branch. For more information, see Force push to a remote branch.

Resolve conflicts from the command line

To give you the most control over each change, you should fix complex conflicts locally from the command line, instead of in GitLab.

Prerequisites:

  1. Open the terminal and check out your feature branch:

    git switch my-feature-branch
    
  2. Rebase your branch against the target branch. In this example, the target branch is main:

    git fetch
    git rebase origin/main
    
  3. Open the conflicting file in your preferred code editor.
  4. Locate and resolve the conflict block:
    1. Choose which version (before or after =======) you want to keep.
    2. Delete the version you don’t want to keep.
    3. Delete the conflict markers.
  5. Save the file.
  6. Repeat the process for each file with conflicts.
  7. Stage your changes:

    git add .
    
  8. Commit your changes:

    git commit -m "Resolve merge conflicts"
    
    caution
    You can run git rebase --abort to stop the process before this point. Git aborts the rebase and rolls back the branch to the state before running git rebase. After you run git rebase --continue, you cannot abort the rebase.
  9. Continue the rebase:

    git rebase --continue
    
  10. Force push the changes to your remote branch:

     git push origin my-feature-branch --force-with-lease
    

Force push to a remote branch

Complex Git operations like squashing commits, resetting a branch, or rebasing rewrite branch history. Git requires a forced update for these changes.

Force pushing is not recommended on shared branches, because you risk destroying others’ changes.

If the branch is protected, you can’t force push unless you:

  • Unprotect it.
  • Allow force pushes.

For more information, see Allow force push on a protected branch.

Restore your backed up branch

If a rebase or force push fails, restore your branch from its backup:

  1. Ensure you’re on the correct branch:

    git checkout my-branch
    
  2. Reset your branch to the backup:

    git reset --hard my-branch-backup
    

Approving after rebase

If you rebase a branch, you’ve added commits. If your project is configured to prevent approvals by users who add commits, you can’t approve a merge request you’ve rebased.

Troubleshooting

For CI/CD pipeline troubleshooting information, see Debugging CI/CD pipelines.

Unmergeable state after /rebase quick action

The /rebase command schedules a background task. The task attempts to rebase the changes in the source branch on the latest commit of the target branch. If, after using the /rebase quick action, you see this error, a rebase cannot be scheduled:

This merge request is currently in an unmergeable state, and cannot be rebased.

This error occurs if any of these conditions are true:

  • Conflicts exist between the source and target branches.
  • The source branch contains no commits.
  • Either the source or target branch does not exist.
  • An error has occurred, resulting in no diff being generated.

To resolve the unmergeable state error:

  1. Resolve any merge conflicts.
  2. Confirm the source branch exists, and has commits.
  3. Confirm the target branch exists.
  4. Confirm the diff has been generated.

/merge quick action ignored after /rebase

If /rebase is used, /merge is ignored to avoid a race condition where the source branch is merged or deleted before it is rebased.