Git rebase rewrites commit history for cleaner, more linear projects. Here's how to use it effectively and safely.
Understanding Rebase#
1# Basic rebase: Move branch to new base
2git checkout feature
3git rebase main
4
5# Before rebase:
6# A---B---C feature
7# /
8# D---E---F---G main
9
10# After rebase:
11# A'--B'--C' feature
12# /
13# D---E---F---G main
14
15# Rebase creates new commits (A', B', C') with different hashesInteractive Rebase#
1# Rebase last 3 commits interactively
2git rebase -i HEAD~3
3
4# Rebase all commits since branching from main
5git rebase -i main
6
7# Interactive rebase opens editor with:
8# pick abc123 First commit
9# pick def456 Second commit
10# pick ghi789 Third commit
11
12# Available commands:
13# pick = use commit
14# reword = edit commit message
15# edit = stop for amending
16# squash = meld into previous commit (keep message)
17# fixup = meld into previous commit (discard message)
18# drop = remove commit
19
20# Example: Squash last 3 commits into one
21# pick abc123 First commit
22# squash def456 Second commit
23# squash ghi789 Third commit
24
25# Example: Reorder and edit
26# pick def456 Second commit (now first)
27# reword ghi789 Third commit (edit message)
28# drop abc123 First commit (removed)Common Rebase Workflows#
1# Keep feature branch up to date with main
2git checkout feature
3git fetch origin
4git rebase origin/main
5
6# Squash all branch commits before merge
7git checkout feature
8git rebase -i main
9# Then squash all commits except the first
10
11# Fixup a specific commit
12git commit --fixup abc123
13git rebase -i --autosquash main
14
15# Autosquash automatically orders fixup commits
16# Original:
17# pick abc123 Original commit
18# pick def456 Some other commit
19# fixup xyz789 fixup! Original commit
20
21# After autosquash reorders:
22# pick abc123 Original commit
23# fixup xyz789 fixup! Original commit
24# pick def456 Some other commitHandling Conflicts#
1# During rebase, if conflicts occur:
2git status # See conflicting files
3
4# Edit files to resolve conflicts
5# Remove conflict markers (<<<<<<<, =======, >>>>>>>)
6
7# Mark as resolved
8git add <resolved-files>
9
10# Continue rebase
11git rebase --continue
12
13# Or abort and return to pre-rebase state
14git rebase --abort
15
16# Skip this commit if not needed
17git rebase --skip
18
19# Use merge strategy for specific files
20git checkout --ours <file> # Keep current branch version
21git checkout --theirs <file> # Keep incoming versionRebase vs Merge#
1# Merge: Preserves history, creates merge commit
2git checkout main
3git merge feature
4
5# Creates:
6# A---B---C feature
7# / \
8# D---E---F---G---H main (H is merge commit)
9
10# Rebase: Linear history, rewrites commits
11git checkout feature
12git rebase main
13git checkout main
14git merge feature # Fast-forward merge
15
16# Creates:
17# D---E---F---G---A'--B'--C' main
18
19# When to use merge:
20# - Public/shared branches
21# - Preserving complete history
22# - Collaborative branches
23
24# When to use rebase:
25# - Personal feature branches
26# - Clean, linear history
27# - Before merging to mainSafe Rebasing Practices#
1# Golden rule: Never rebase public/shared commits
2
3# Create backup before risky rebase
4git branch backup-feature feature
5
6# Use reflog to recover from mistakes
7git reflog
8# abc123 HEAD@{0}: rebase finished
9# def456 HEAD@{1}: rebase: First commit
10# ghi789 HEAD@{2}: checkout: moving from main to feature
11
12git reset --hard ghi789 # Restore to before rebase
13
14# Force push after rebase (only your branches!)
15git push --force-with-lease origin feature
16
17# --force-with-lease is safer than --force
18# It fails if remote has commits you don't haveAdvanced Rebase Operations#
1# Rebase onto specific commit
2git rebase --onto main feature~3 feature
3# Rebases only last 3 commits of feature onto main
4
5# Split a commit
6git rebase -i HEAD~3
7# Mark commit as "edit"
8# When rebase stops at that commit:
9git reset HEAD~1
10git add file1.js
11git commit -m "First part"
12git add file2.js
13git commit -m "Second part"
14git rebase --continue
15
16# Rebase with merge commits
17git rebase -i --rebase-merges main
18
19# Execute command after each commit
20git rebase -i --exec "npm test" main
21# Runs tests after each rebased commit
22
23# Preserve merge commits
24git rebase -p mainTeam Workflows#
1# Feature branch workflow with rebase
2# 1. Create feature branch
3git checkout -b feature/new-thing main
4
5# 2. Make commits
6git commit -m "Add feature"
7
8# 3. Before PR, update and clean up
9git fetch origin
10git rebase origin/main
11
12# 4. Interactive rebase to squash/cleanup
13git rebase -i origin/main
14
15# 5. Force push (since we rebased)
16git push --force-with-lease origin feature/new-thing
17
18# 6. Create PR, get review
19
20# 7. If main updated during review, rebase again
21git fetch origin
22git rebase origin/main
23git push --force-with-lease origin feature/new-thing
24
25# 8. Merge via PR (usually squash merge)Git Configuration for Rebasing#
1# Auto-setup remote tracking
2git config --global push.default current
3git config --global push.autoSetupRemote true
4
5# Always use rebase when pulling
6git config --global pull.rebase true
7
8# Autosquash by default
9git config --global rebase.autosquash true
10
11# Auto-stash before rebase
12git config --global rebase.autoStash true
13
14# Show conflicts in 3-way diff
15git config --global merge.conflictstyle diff3
16
17# Use better diff algorithm
18git config --global diff.algorithm histogramRebase Aliases#
1# Useful aliases
2git config --global alias.rb 'rebase'
3git config --global alias.rbi 'rebase -i'
4git config --global alias.rbc 'rebase --continue'
5git config --global alias.rba 'rebase --abort'
6git config --global alias.rbs 'rebase --skip'
7
8# Rebase onto main
9git config --global alias.rom 'rebase origin/main'
10
11# Interactive rebase from main
12git config --global alias.rbim 'rebase -i origin/main'
13
14# Fixup last commit into previous
15git config --global alias.fixup 'commit --fixup HEAD'
16
17# Squash all commits since main
18git config --global alias.squash '!git reset --soft $(git merge-base HEAD origin/main) && git commit'Troubleshooting#
1# Rebase stuck or confused
2git rebase --abort
3git reflog
4git reset --hard HEAD@{n}
5
6# Wrong commits rebased
7git reflog
8git reset --hard <commit-before-rebase>
9
10# Conflicts on every commit
11# Might be rebasing wrong way
12git rebase --abort
13# Check you're rebasing feature onto main, not main onto feature
14
15# Lost commits after rebase
16git reflog
17# All commits are still there, find and checkout
18
19# Accidentally pushed rebased commits
20# If others have pulled, you need to coordinate
21# They need to:
22git fetch origin
23git reset --hard origin/branch
24# Or:
25git pull --rebase origin branchBest Practices#
Do:
✓ Rebase local/personal branches
✓ Clean up commits before PR
✓ Use --force-with-lease
✓ Create backup branches
Don't:
✗ Rebase public/shared branches
✗ Rebase after pushing to shared repo
✗ Use --force on main/master
✗ Rebase without understanding consequences
Workflow:
✓ Rebase feature onto main regularly
✓ Squash fixup commits
✓ Write meaningful commit messages
✓ Test after rebase
Conclusion#
Git rebase creates cleaner history but requires care. Use it for personal branches before merging, always use --force-with-lease for pushing, and never rebase shared commits. Master interactive rebase for cleaning up commits before pull requests. When in doubt, merge is safer.