Git Course 0%

git rebase

Intermediate Git CLI Dangerous ≈ 8 min

Summary: git rebase <base> takes the commits your branch added and applies them again on top of <base>, producing new commits with new hashes and a straight history.

Dangerous — rebasing rewrites commits. It is routine on a branch only you have, and disruptive on any branch someone else has checked out, because their copies no longer match (lesson 2.7).

What it does

Finds the commits on your branch that are not on <base>, sets your branch to <base>, and re-applies each of those commits in order. Each re-application can conflict, and each produces a new commit: same change and message, different parent, therefore a different hash.

Why it exists

To bring a branch up to date without a merge commit, and to tidy a messy branch before review. The result is a history that reads as though the work had started today.

When to use it

  • Updating your own unshared branch onto a newer main before asking for review.
  • Cleaning up commits before a merge request, with -i (lesson 18.5).
  • When your team requires a linear history and the platform asks you to rebase.

When not to use it

  • On main, a release branch, or any branch a colleague has.
  • After reviewers have started commenting: their comments attach to commits you are about to replace.
  • When the rebase conflicts repeatedly: abort and git merge instead.

Syntax

Form Meaning
git rebase <base> Replay the current branch's commits onto <base>
git rebase --continue After resolving a conflict, carry on
git rebase --skip Drop the commit being replayed Dangerous
git rebase --abort Undo everything, back to before the rebase
git rebase -i <base> Interactive: reorder, squash, reword, drop
git rebase --onto <new> <old> <branch> Move a branch from one base to another

Examples

Terminal
$ git switch docs/12-windows-install-steps
$ git rebase main
Successfully rebased and updated refs/heads/docs/12-windows-install-steps.

The hash changes, which is the whole point and the whole risk:

Terminal
$ git log --oneline --graph --all --decorate
* 5f181fc (HEAD -> docs/12-windows-install-steps) docs: add Windows steps to installation guide (#12)
* 1a01760 (origin/main, origin/HEAD, main) feat: add Coast Walk trail (#29)
| * 510f1e0 (origin/docs/12-windows-install-steps) docs: add Windows steps to installation guide (#12)
|/  
* 8fa922e (tag: v1.2.0) Initial import of trailguide

Two commits with the same message: the new one on top of main, and the original still on the remote. So the next push is refused:

Terminal
$ git push
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.

Do not follow that hint after a rebase; replace the remote branch instead:

Terminal
$ git push --force-with-lease
To https://gitlab.com/northwind-trails/trailguide.git
 + 510f1e0...5f181fc docs/12-windows-install-steps -> docs/12-windows-install-steps (forced update)

A conflict pauses the rebase and names the commit being replayed:

Terminal
$ git rebase main
Auto-merging docs/faq.md
CONFLICT (content): Merge conflict in docs/faq.md
error: could not apply e755292... docs: reword licence answer (#42)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".

Expected result

Your branch's commits are re-created on the new base with new hashes; the originals remain until nothing references them. The working tree ends on the rebased branch. A pushed branch then needs --force-with-lease.

Common mistakes

  • git pull after a rebase, following the push hint. It merges the pre-rebase commits back in. Use --force-with-lease on your own branch.
  • Plain --force. It overwrites even if a colleague pushed since; --force-with-lease checks first.
  • Rebasing a shared branch. Everyone else's clone diverges.
  • --skip to silence a conflict. It deletes the commit.
  • git commit mid-rebase instead of git rebase --continue, which leaves a stray commit. Abort and start again.

How to undo or recover

  • Mid-rebase: git rebase --abort restores everything.
  • After finishing, if it went wrong: git reflog shows where the branch was before, then git reset --hard <hash> returns to it (lesson 12.1).
  • After force-pushing a bad rebase: the same reflog recovery locally, then another --force-with-lease to put the good version back, and a message to the team.

In VS Code

Command Palette → Git: Rebase Branch…. The force push appears on the sync menu once the branch has diverged; check that Git: Use Force Push With Lease is enabled in Settings.

In IntelliJ IDEA

Branches popup → point at a branch → Rebase current onto…, or Git → Rebase… for the full dialog including Interactive. Force push offers --force-with-lease by default.

git merge is the safe alternative · git push with --force-with-lease is required afterwards · git reflog recovers from a bad rebase · git pull --rebase applies the same idea when pulling.

Lessons that use this command

Rebasing explained; merge or rebase? · Rebase conflicts · What rewrites history.

Key terms

Rebase Rewriting history Hash (SHA) Merge