git rebase replays your branch's commits on top of another commit, giving a straight history instead of a merge commit. Run git rebase main from your feature branch, fix any conflicts, then git rebase --continue. Use git rebase -i to squash, reword or drop commits, and git rebase --abort to back out.
| Goal | Command |
|---|---|
| Move your branch onto the latest main | git rebase main |
| Edit the last 4 commits | git rebase -i HEAD~4 |
| Carry on after fixing a conflict | git add <file> then git rebase --continue |
| Skip the commit that is stuck | git rebase --skip |
| Cancel and go back to how it was | git rebase --abort |
| Fold fixup! commits automatically | git rebase -i --autosquash main |
Updated
Rebase is the git command people fear most, mainly because it rewrites commits. The graph below shows exactly what changes when you merge versus rebase, the planner lets you try an interactive rebase on sample commits, and the last sections cover conflicts, the one rule that keeps teammates safe, and how to get back a branch after a rebase went wrong.
git rebase -i opens a todo list with one line per commit, oldest at the top. Change the word at the start of a line, save and close the editor, and git carries out the list from top to bottom.
| Command | What it does |
|---|---|
| pick | Keep the commit as it is |
| reword | Keep the commit but edit its message |
| edit | Stop after this commit so you can amend it or split it |
| squash | Fold into the commit above and combine both messages |
| fixup | Fold into the commit above and drop this message |
| fixup -C | Fold into the commit above and use this commit's message |
| exec | Run a shell command, for example your tests |
| break | Pause here; resume with git rebase --continue |
| drop | Remove the commit |
| label / reset / merge | Name points and rebuild merges (used with --rebase-merges) |
| update-ref | Move another branch ref to this point (used with --update-refs) |
Fetch first so main is current, rebase, resolve any conflict, then push the rewritten branch safely.
git switch feature/login
git fetch origin
git rebase origin/main
# conflict? edit the file, then:
git add src/login.ts
git rebase --continue
# changed your mind at any point:
git rebase --abort
# branch was already pushed:
git push --force-with-leaseFind the line just before the rebase began and reset the branch back to it.
git reflog
# a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feature/login
# 9f8e7d6 HEAD@{5}: commit: add login form <- the old tip
git reset --hard HEAD@{5}
# or, straight after the rebase:
git reset --hard ORIG_HEAD--onto takes three points: the new base, the old base, and the branch. Only the commits after the old base move.
feature-b was started from feature-a. This puts only feature-b's own commits on top of main.
git rebase --onto main feature-a feature-b
Git finds the commit where your branch and the target split, saves your commits as patches, moves your branch to the target, and applies the patches one at a time. The result looks like you started your work today from the latest main.
Because each replayed commit has a different parent, it gets a different hash. That is why a rebased branch needs a force push, and why rebasing shared history causes trouble.
The reflog records every place HEAD and each branch tip has pointed, locally. Rebased-away commits stay reachable through it, so nothing is lost straight away.
Git prunes reflog entries during garbage collection: by default reachable entries after 90 days and unreachable ones after 30 days. Recover a bad rebase soon, not months later.
Merge keeps the real history and adds a merge commit, which is safest for shared branches. Rebase gives a straight line that is easier to read and bisect, which suits your own feature branch before it is reviewed. Many teams rebase privately and merge publicly.
If it is still running, git rebase --abort puts everything back. If it already finished, run git reflog, find the entry just before the rebase started, and git reset --hard to that hash. ORIG_HEAD also points at the old tip right after a rebase, unless another command changed it.
Do not rebase commits that other people have already based work on. Rebasing makes new commits with new hashes, so anyone holding the old ones ends up with duplicate history and confusing conflicts.
Both fold a commit into the one above it. squash opens the editor so you can combine both messages; fixup throws away the folded commit's message and keeps the earlier one. fixup -C keeps the folded commit's message instead.
Each commit is applied again on the new base, and a commit that touched the same lines as the base cannot be applied automatically. Edit the file, git add it, and run git rebase --continue. You may hit a conflict once per replayed commit.
Related: Git cheat sheet, Git worktree guide, Rename a git branch, GitHub personal access tokens.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.