Advanced git rebase — linear history, stacked PRs, --update-refs, --onto. Use when rebasing branches, cleaning history, managing PR stacks, or fixing merge-heavy branches.
Advanced git rebase — linear history, stacked PRs, --update-refs, --onto. Use when rebasing branches, cleaning history, managing PR stacks, or fixing merge-heavy branches.
user-invocable
false
allowed-tools
Bash, Read
created
"2026-01-30T00:00:00.000Z"
modified
"2026-05-09T00:00:00.000Z"
reviewed
"2026-01-30T00:00:00.000Z"
Git Rebase Patterns
Advanced rebase techniques for maintaining linear history, managing stacked PRs, and cleaning up commit history.
When to Use This Skill
Use this skill when...
Use something else when...
Rebasing feature branches onto updated main
Creating branches → git-branch-naming
Cleaning up commit history before PR
Creating PRs → git-branch-pr-workflow
Managing stacked PRs (PR chains)
Simple commits → git-commit-workflow
Converting merge-heavy branches to linear
Basic git operations → git-cli-agentic
Linear History Basics
Trunk-Based Development
# Feature branch lifecycle (keep short - max 2 days)
git switch main
git pull origin main
git switch -c feat/user-auth
# Daily rebase to stay current
git switch main && git pull
git switch feat/user-auth
git rebase main
# Interactive cleanup before PR
git rebase -i main
# Squash, fixup, reword commits for clean history# Push and create PR
git push -u origin feat/user-auth
Squash Merge Strategy
Maintain linear main branch history:
# Manual squash merge
git switch main
git merge --squash feat/user-auth
git commit -m "feat: add user authentication system
- Implement JWT token validation
- Add login/logout endpoints
- Create user session management
Closes #123"
Interactive Rebase Workflow
Clean up commits before sharing:
# Rebase last 3 commits
git rebase -i HEAD~3
# Common rebase commands:# pick = use commit as-is# squash = combine with previous commit# fixup = squash without editing message# reword = change commit message# drop = remove commit entirely# Example rebase todo list:
pick a1b2c3d feat: add login form
fixup d4e5f6g fix typo in login form
squash g7h8i9j add form validation
reword j1k2l3m implement JWT tokens
Advanced Rebase Flags
Reapply Cherry-Picks (--reapply-cherry-picks)
Problem: After merging trunk into your feature branch multiple times (via git merge main), you want to rebase onto fresh trunk. Default rebase behavior may create conflicts or duplicate commits.
Solution:--reapply-cherry-picks detects commits that were already applied via merge and drops the merge commits, keeping only your original changes.
# Scenario: You merged main into your branch a few times
git log --oneline
# abc123 Merge branch 'main' into feat/auth# def456 feat: add login endpoint# ghi789 Merge branch 'main' into feat/auth# jkl012 feat: add user validation# Rebase onto fresh main, dropping merge commits
git fetch origin
git rebase --reapply-cherry-picks origin/main
# Result: Clean linear history with just your feature commits# jkl012 feat: add user validation# def456 feat: add login endpoint
When to use:
After merging trunk into your branch to resolve conflicts
Converting a merge-heavy branch to linear history
Before creating a PR to clean up integration merges
Update Refs (--update-refs)
Problem: With stacked PRs (PR chains), rebasing one branch requires manually rebasing all dependent branches. Moving commits between branches in the stack is painful.
Solution:--update-refs automatically updates all branches in the chain when you rebase. Combined with interactive rebase, you can reorganize commits across your entire PR stack in one operation.
# Scenario: Stacked PRs# main <- feat/auth-base <- feat/auth-oauth <- feat/auth-refresh# Rebase the entire stack onto updated main
git switch feat/auth-refresh
git rebase --update-refs main
# All three branches (auth-base, auth-oauth, auth-refresh) are updated# No manual rebasing of each branch needed# Interactive rebase to move commits between branches
git rebase -i --update-refs main
# In the editor, move commit lines around to reorganize the stack:# pick abc123 feat: add auth base # Will update feat/auth-base# pick def456 feat: add OAuth support # Will update feat/auth-oauth# pick ghi789 feat: add token refresh # Will update feat/auth-refresh
Stacked PR workflow with update-refs:
# Create PR stack
git switch main
git pull origin main
# First PR: Base authentication
git switch -c feat/auth-base
# ... make commits ...
git push -u origin feat/auth-base
# Second PR: OAuth (depends on first)
git switch -c feat/auth-oauth
# ... make commits ...
git push -u origin feat/auth-oauth
# Third PR: Token refresh (depends on second)
git switch -c feat/auth-refresh
# ... make commits ...
git push -u origin feat/auth-refresh
# Main updated - rebase entire stack
git fetch origin
git switch feat/auth-refresh
git rebase --update-refs origin/main
# All branches rebased in one command
git push --force-with-lease origin feat/auth-base
git push --force-with-lease origin feat/auth-oauth
git push --force-with-lease origin feat/auth-refresh
When to use:
Managing stacked PRs (PR chains with dependencies)
Reorganizing commits across multiple branches
Keeping branch hierarchies in sync during rebase
Explicit Base Control (--onto)
Problem: Git's automatic base detection can be ambiguous or incorrect. You want precise control over where commits are rebased.
Solution:--onto explicitly specifies the new base, bypassing Git's base detection heuristics.
# Syntax: git rebase --onto <newbase> <upstream> <branch># Translates to: Take commits from <upstream>..<branch> and put them onto <newbase># Common pattern: Rebase last N commits onto a specific branch
git rebase --onto origin/develop HEAD~5
# Takes your last 5 commits and puts them on top of origin/develop# Equivalent to: git rebase --onto origin/develop HEAD~5 HEAD# Example: Move feature commits from old base to new base# Scenario: You branched from develop, but should have branched from main
git switch feat/payment
git rebase --onto main develop feat/payment
# Takes commits from develop..feat/payment and moves them onto main# Example: Rebase specific commit range# Move commits from abc123 to def456 onto main
git rebase --onto main abc123^ def456
# The ^ includes abc123 in the range# Example: Extract commits to new branch# You have commits on feat/auth that should be on separate branch
git switch -c feat/auth-ui feat/auth # Create new branch
git rebase --onto main feat/auth~3 feat/auth-ui
# Takes last 3 commits from feat/auth and puts them on main
Common --onto patterns:
Pattern
Command
Use Case
Last N commits on trunk
git rebase --onto origin/main HEAD~N
Rebase recent work onto updated trunk
Change branch base
git rebase --onto <new-base> <old-base>
Fix branch created from wrong base
Extract commit range
git rebase --onto <target> <start>^ <end>
Move specific commits to new location
Interactive with onto
git rebase -i --onto <base> HEAD~N
Clean up and rebase last N commits
When to use:
When you don't trust Git's automatic base detection
Rebasing a specific number of recent commits (HEAD~N pattern)
Changing the base of a branch after it was created
Extracting a subset of commits to a new location
Combining Advanced Flags
These flags work together for powerful workflows:
# Rebase stacked PRs with cherry-pick detection
git rebase --reapply-cherry-picks --update-refs origin/main
# Interactive rebase with explicit base and branch updates
git rebase -i --onto origin/main HEAD~10 --update-refs
# Clean up merged history and update dependent branches
git rebase --reapply-cherry-picks --update-refs --onto origin/develop origin/main
Conflict Resolution
# When rebase conflicts occur
git rebase main
# Fix conflicts in editor
git add resolved-file.txt
git rebase --continue# If rebase gets messy, abort and merge instead
git rebase --abort
git merge main
Safe Force Pushing
# Always use --force-with-lease to prevent overwriting others' work
git push --force-with-lease origin feat/branch-name
# Never force push to main/shared branches# Use this alias for safety:
git config alias.pushf 'push --force-with-lease'
Quick Reference
Operation
Command
Rebase onto main
git rebase main
Interactive rebase
git rebase -i HEAD~N
Rebase with cherry-pick cleanup
git rebase --reapply-cherry-picks origin/main
Rebase stacked PRs
git rebase --update-refs main
Rebase last N commits
git rebase --onto origin/main HEAD~N
Change branch base
git rebase --onto <new> <old>
Abort failed rebase
git rebase --abort
Continue after conflict
git rebase --continue
Skip problematic commit
git rebase --skip
Troubleshooting
Rebase Conflicts Are Too Complex
# Abort rebase and use merge instead
git rebase --abort
git merge main
Branch Diverged from Remote
# Pull with rebase to maintain linear history
git pull --rebase origin feat/branch-name
# Or reset if local changes can be discarded
git fetch origin
git reset --hard origin/feat/branch-name
Lost Commits After Rebase
# Find lost commits in reflog
git reflog
# Restore to previous state
git reset --hard HEAD@{N}