Skip to content
masterclass Buddy

Git · Command

git rebase

git rebase takes the commits that are unique to a branch and replays them on a different base commit, creating new commits. It can also rewrite a branch in place by reordering, editing, squashing or dropping commits in interactive mode.

Last updated

How it works

First, rebase lists the commits on your branch that are not already in <upstream>. Commits whose changes are already upstream are left out. Next, it detaches HEAD at the new base, which is <upstream> or the --onto target. It then replays each listed commit in order, much like running cherry-pick on each one. Finally, it moves the branch ref to the last replayed commit. If you don't give an upstream, it uses the branch's configured upstream and assumes --fork-point. The default backend is merge, which uses the ort strategy. The older apply backend, based on git-am, is still available with --apply.

Syntax

git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase> | --keep-base] [<upstream> [<branch>]]
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)

Parameters

NameTypeDescription
<upstream>commit-ishThe branch or commit to compare against. Any valid commit works. If omitted, the branch's configured upstream is used.
<branch>branch nameThe branch to rebase. Defaults to HEAD. If you give it, rebase checks it out first.
--onto <newbase>commit-ishWhere the new commits will be created, if different from <upstream>. 'A...B' is shorthand for the merge base of A and B.
--keep-baseflagReplays the commits onto the merge base of <upstream> and <branch>, so the branch's base stays the same. Implies --reapply-cherry-picks and --no-fork-point.
-i, --interactiveflagOpens the todo list of commits in an editor so you can change it before the rebase runs.
--continue | --skip | --abort | --quitmode flagControl a rebase that has stopped. --continue resumes after you resolve conflicts, --skip drops the current patch, --abort restores the original branch, and --quit stops without resetting HEAD.
--autostashflagStashes uncommitted changes before the rebase and reapplies them afterwards.

Returns

On success, <branch> is the current branch and points at the rewritten commits. If a conflict, an 'edit' step or a failed exec stops the rebase, it pauses and waits for --continue, --skip or --abort.

Key points

  • If a conflict happens, the rebase pauses at the commit that caused it. Resolve the conflict, git add the files, then run --continue. You can also use --abort to go back to where you started, or --skip to drop that commit.
  • --onto separates two things: <upstream> decides which commits get moved, and --onto decides where they land. For example, 'git rebase --onto master next topic' moves topic's own commits off next and onto master.
  • --keep-base lets you clean up a feature branch without moving it forward onto a newer upstream.
  • In the interactive todo list, you can change 'pick' to edit, reword, squash, fixup, drop or break, or add exec lines. Lines run from top to bottom.
  • With --autosquash, commits made with 'git commit --fixup' or '--squash' are moved next to their target commit and squashed into it automatically. Setting rebase.autoSquash turns this on by default.
  • --exec <cmd> adds a command, such as a test run, after each commit that is created. If the command fails, the rebase stops so you can fix that commit.
  • By default, merge commits are dropped and the history becomes linear. Use -r/--rebase-merges to recreate the branch-and-merge structure instead.
  • --update-refs also moves any other branches that point into the rebased range, which helps with stacked branches. Branches that are checked out in a worktree are not updated.

Common mistakes

  • During a rebase, 'ours' means the upstream plus the commits replayed so far, and 'theirs' means your branch. That is the opposite of a merge, which matters for -Xours and -Xtheirs.
  • Rebasing a branch that others have already built on forces everyone downstream to repair their history by hand.
  • --autostash makes it possible to rebase with uncommitted changes, but reapplying the stash at the end can still produce conflicts.
  • ORIG_HEAD may no longer point at the old tip if commands like git reset ran during the rebase. Use the branch reflog (@{1}) to get back to the old tip.

Example: Update a feature branch and tidy fixup commits

#!/usr/bin/env bash
set -euo pipefail

# Bring the latest main into this repo
git fetch origin

# Work on the feature branch
git switch feature

# Record a fix aimed at an earlier commit
git commit --fixup=HEAD~2 -am ""

# Replay feature onto origin/main, squash fixups,
# and run the tests after every rewritten commit
git rebase -i --autosquash --autostash \
  --exec "npm test" origin/main

# If it stops on a conflict:
#   git status            # see the conflicted files
#   git add <file>        # mark each one resolved
#   git rebase --continue # or --skip / --abort

# Compare the old and new history
git range-diff @{1}...HEAD

# Publish the rewritten branch safely
git push --force-with-lease

The script moves a feature branch onto the updated origin/main, folds a fixup commit into its target, runs the tests at each step, and compares the result with the old tip from the reflog before force-pushing.

When to use it

Keep a topic branch current

Your PR branch has fallen behind main. Rebasing it onto origin/main gives a linear history with no merge commit when it is merged.

Clean up commits before review

Use an interactive rebase to reword unclear messages, squash work-in-progress commits and drop debugging commits before you open a pull request.

Move a branch to a different base

A feature was started on 'next' but now needs to ship from 'master'. 'git rebase --onto master next topic' moves only the feature's own commits.

Remove a range of bad commits

To cut two broken commits out of the middle of a branch, rebase the commits after them onto the commit just before them with --onto.

Interview questions

QWhat does git rebase actually do to commits, and how is that different from git merge?

Rebase finds your branch's commits that are missing from the upstream, then replays them one by one on the new base, like a series of cherry-picks. The results are new commits with new IDs, and the branch ref is moved to them. A merge keeps the existing commits and adds a merge commit. Rebase rewrites history to make it linear, which is why the docs warn against rebasing branches that others build on.

Follow-up: Why can an unchanged rebase still create new commits? With -f/--force-rebase (implied by options like --committer-date-is-author-date), rebase replays every commit instead of fast-forwarding over the ones that are unchanged, so every commit gets a new ID.

QExplain 'git rebase --onto A B C'.

First, C is checked out. The commits in B..C, meaning those reachable from C but not from B, are chosen for replay. They are then replayed on top of A. Here B decides which commits move and A decides where they land. This lets you detach a topic from an intermediate branch, or delete a range with something like 'git rebase --onto X~5 X~3 X'.

Follow-up: How is --keep-base different from --fork-point? Both use a merge base, but --keep-base uses it as the place where new commits are created, while --fork-point uses the reflog to decide which commits get rebased.

QYou resolved a conflict during a rebase, but the result looks wrong. How do you investigate and recover?

While the rebase is paused, 'git rebase --show-current-patch' shows the commit being applied (it is the same as git show REBASE_HEAD). Remember that 'ours' is the upstream side here, not your branch. If things go badly, --abort resets HEAD to the original branch. After a finished rebase, the old tip is still in the branch reflog at @{1}.

Follow-up: How can you avoid resolving the same conflicts again on later rebases? Turn on git rerere so that recorded resolutions are reused, and use --no-rerere-autoupdate to check the reused resolution before it is staged.

  • git cherry-pick
  • git merge
  • git commit --fixup
  • git reflog
  • git range-diff
  • git merge-base
  • git pull --rebase
  • git rerere

Source: Git - git-rebase Documentation. Checked 2026-11-02.