Concepts
Git Rebase Deep Dive
Understand Git Rebase internals, interactive rebasing, conflict resolution strategies, and best practices.
- Readers who want the history model before advanced commands
- A basic sense that commits are not just a file list
- Treating a concepts page like a command how-to
What you will learn
- Understand the core purpose of Git Rebase Deep Dive
- Master the basic usage and common options of Git Rebase Deep Dive
- Understand Git Rebase internals, interactive rebasing, conflict resolution strategies, and best practices.
- Understand key concepts: Overview
- Know when to use this feature and when to avoid it
Start with a problem
You've encountered a conceptual question while using Git — you roughly know what it means, but you're not entirely sure about its precise definition and boundaries.
Overview
git rebase is one of Git's most powerful—and dangerous—commands. It rewrites history by replaying commits, commonly used to:
- Linearize history
- Edit commit messages, split/squash commits
- Sync feature branches with latest upstream
Internal Mechanics
How It Works
flowchart LR
A[Original branch] --> B[Compute diff]
B --> C[Create temp area]
C --> D[Apply patches one by one]
D --> E[Generate new commits]
E --> F[Update branch pointer]
Rebase actually:
- Finds the fork point (merge-base)
- Saves current branch commits as patch sequence
- Switches to target branch
- Applies patches one by one (via
git amor internal sequencer) - Updates branch ref to new commit chain
Sequencer (git-rebase--sequencer)
Git 2.30+ uses a C-rewritten sequencer with major performance gains:
- Native merge conflict handling
- Supports
--autosquash,--fixup,--squash - Better progress reporting
Interactive Rebase
git rebase -i HEAD~5
# Or target a branch
git rebase -i main
Common Commands
| Command | Short | Effect |
|---|---|---|
pick | p | Keep commit |
reword | r | Edit commit message |
edit | e | Pause, amend content |
squash | s | Meld into previous commit |
fixup | f | Meld, discard message |
drop | d | Discard commit |
exec | x | Run shell command |
break | b | Pause here |
label | l | Label current position |
reset | - | Reset to label |
merge | m | Create merge commit |
Practical Patterns
# Auto-squash fixup!/squash! commits
git rebase -i --autosquash main
# Preserve merge commits (don't flatten)
git rebase -i --rebase-merges main
# Only rewrite commit messages
git rebase -i --rebase-merges --committer-date-is-author-date HEAD~3
Conflict Resolution
During Rebase
# Rebase pauses on conflict
# After resolving:
git add <resolved-files>
git rebase --continue
# Abort entirely
git rebase --abort
# Skip current commit (dangerous)
git rebase --skip
Strategies
# Use merge tool
git mergetool
# Keep our version
git checkout --ours <file>
# Keep their version
git checkout --theirs <file>
# Show conflict markers
git diff --check
Advanced Usage
--rebase-merges Preserves Topology
# Preserve merge commit topology
git rebase -i --rebase-merges main
The generated todo list uses label, reset, merge for precise merge topology control.
Rebasing Branches with Merges
# Default: flattens merges
git rebase main
# Preserve merge structure
git rebase --rebase-merges main
Signatures & Dates
# Keep author date, use now as committer date
git rebase --committer-date-is-author-date
# Re-sign all commits
git rebase --signoff main
Best Practices
- Only rebase local unpushed commits — rebasing pushed breaks others' history
- Use
--autosquashwithfixup!/squash!— mark at commit time, auto-squash on rebase - Create backup branch before large rebase —
git branch backup-before-rebase - Use
--rebase-mergesto preserve merge topology — avoids flattening complex merges - Small frequent rebases — easier conflict resolution than one big rebase
Common Pitfalls
| Pitfall | Consequence | Avoidance |
|---|---|---|
| Rebase pushed branch | Team history divergence | Only rebase local branches |
git rebase --skip mid-rebase | Lost commits | Resolve conflicts carefully, don't skip |
Forget --rebase-merges | Lost merge topology | Add flag for complex branch structures |
| Rebase with dirty worktree | Failure or pollution | git stash or commit first |
Try it yourself
- Practice the git-rebase-deep command in a test repository and observe state changes before and after
- Experiment with different options and compare the output differences
- Simulate a real scenario where you would need to use this, and walk through the full process
Continue Learning
commands/git-rebase— git rebase command referenceinternals/rebase-internals-and-sequencer— Rebase internalsconcepts/git-merge-deep— Git Merge Deep Diveworkflows/prepare-commits-before-pull-request— Pre-PR commit cleanup