Skip to main content

What is Rebasing?

Rebasing is the second way of combining work between branches. While merge creates a commit with two parents, rebase essentially takes a set of commits, “copies” them, and places them down somewhere else.
The advantage of rebasing is that it creates a nice linear sequence of commits. The commit log/history becomes much cleaner when only rebasing is used.

How Rebase Works

The Rebase Process

When you rebase a branch onto another:
  1. Git finds the common ancestor
  2. Temporarily saves your commits
  3. Moves your branch to the target
  4. Re-applies your commits one by one on top
  5. Creates new commit copies with different IDs

Sequential vs. Parallel

Rebase makes parallel development appear sequential:
  • Reality: Features developed in parallel
  • After rebase: Looks like one feature was built on top of the other

Visual Example

Before rebase:
       C3 (main)
      /
C0-C1
      \
       C2 (bugFix*)
After git rebase main:
C0-C1-C3 (main)-C2' (bugFix*)

(C2 still exists but faded)
Note:
  • C2' is a copy of C2 with a new commit ID
  • Original C2 still exists somewhere (shown faded in visualization)
  • History is now linear: C0 -> C1 -> C3 -> C2'

The Rebase Introduction Level

Level Goal

Create divergent branches and rebase them into a linear history:
1

Create and commit on bugFix

git checkout -b bugFix
git commit
Creates C2 on the bugFix branch.
2

Commit on main

git checkout main
git commit
Creates C3 on the main branch.
3

Rebase bugFix onto main

git checkout bugFix
git rebase main
Copies C2 to create C2' on top of main.
4

Fast-forward main (optional)

git checkout main
git rebase bugFix
Moves main forward to C2'.

Expected Result

main (bugFix*)
  |
  C2'
  |
  C3
  |
  C1
  |
  C0
A completely linear history.

Rebase Direction

”Rebase ONTO”

The command git rebase <target> means:
“Take my current branch and rebase it ONTO the target”
git checkout feature    # Current: feature
git rebase main        # Rebase feature ONTO main
Think of rebase as moving your branch to have a new “base” - hence “re-base”.

Common Pattern

Typical workflow after rebasing:
  1. Rebase your feature onto main (linearize)
  2. Switch to main
  3. Rebase main onto feature (fast-forward)
Result: Both branches point to the same linear history.

Commit Copies

Why Copies?

Rebasing creates new commits because:
  • Commits are immutable (can’t change their parents)
  • New commits need different parent pointers
  • Different parent = different commit ID

Identifying Copies

In Learn Git Branching:
  • Original: C2
  • Copy: C2' (prime mark)
  • Original shown faded/translucent
  • Copy shown solid at new location
{
  id: "C2",
  parents: ["C1"]  // Original parent
}

Rebase vs. Merge

Visual Comparison

Merge Result:
       C3
      /  \
 C0-C1    C4 (merge commit)
      \  /
       C2
Rebase Result:
C0-C1-C3-C2' (linear)

Key Differences

Merge

  • Preserves true history
  • Non-destructive
  • Creates merge commits
  • Shows parallel development
  • History can be complex

Rebase

  • Creates linear history
  • Rewrites history
  • No merge commits
  • Appears sequential
  • Cleaner log

When to Use Rebase

Good Use Cases

Feature Branches

Rebase onto main before merging to keep history linear.

Personal Branches

Clean up your work before sharing with others.

Local Changes

Rebase local commits that haven’t been pushed.

Clean History

Make commit history easier to follow and understand.

When NOT to Rebase

Never rebase commits that have been pushed to shared/public repositories. This rewrites history and causes problems for others.

Advanced Rebasing

Interactive Rebase

While not in Learn Git Branching’s basic levels, interactive rebase allows:
  • Reordering commits
  • Combining commits (squash)
  • Editing commit messages
  • Dropping commits
git rebase -i HEAD~3

Rebase with Specific Range

Rebase specific commits:
git rebase --onto main feature bugfix
Means: “Take commits from bugfix that aren’t in feature, and put them on main.”

The Golden Rule of Rebasing

The Golden Rule: Never rebase commits that exist outside your repository.Once you push commits, consider them immutable. Only rebase local changes.
Why?
  • Other developers may have based work on your commits
  • Rewriting shared history causes conflicts
  • Forces others to re-sync their work

Rebase Implementation

From the source code:
// From rebasing.js
goalTreeString: {
  branches: {
    main: { target: "C3" },
    bugFix: { target: "C2'" }  // Copied commit
  },
  commits: {
    C2: { parents: ["C1"] },      // Original (faded)
    C2': { parents: ["C3"] }      // Copy with new parent
  }
}

Practical Examples

Example 1: Update Feature Branch

1

Develop feature

git checkout -b feature
git commit  # C2
git commit  # C3
2

Main progresses

git checkout main
git commit  # C4
3

Rebase to stay current

git checkout feature
git rebase main  # Creates C2' and C3' on top of C4

Example 2: Clean Feature Before Merge

# Feature is ready
git checkout feature
git rebase main  # Get latest changes, linearize

# Now merge (will be fast-forward)
git checkout main
git merge feature
Result: Clean, linear history on main.

Rebase Mechanics

Fast-Forward After Rebase

After rebasing a branch onto main, main can fast-forward: After rebase:
main --> C3
         |
         C2' (feature*)
After git checkout main; git rebase feature:
main* --> C2'
          |
          C3
No merge commit needed - main just moves forward.

Ancestor Relationships

After rebase, the rebased branch becomes a descendant:
  • Before: bugFix and main are siblings (both from C1)
  • After: bugFix is a child of main (based on C3)

Handling Conflicts During Rebase

While Learn Git Branching doesn’t show conflicts, in real Git:

If Conflicts Occur

git rebase main
# Conflict occurs

# Fix conflicts in files
git add <file>
git rebase --continue

# Or abort
git rebase --abort
Conflicts are resolved commit-by-commit during replay.

Best Practices

Rebase Often

Regularly rebase feature branches onto main to avoid big conflicts.

Before Pushing

Rebase and clean up commits before pushing to shared repository.

Communicate

Let team know if rebasing shared branches (though generally avoid this).

Keep It Local

Only rebase commits that exist in your local repository.

Understanding the Visualization

Original Commits

After rebase, original commits appear:
  • Faded/translucent
  • Still in their original position
  • Eventually garbage collected (in real Git)

Copied Commits

  • Solid/opaque
  • In new position (on top of target)
  • Active and referenced by branch

Why Show Both?

Learn Git Branching shows both to help you understand:
  • What changed (location and parent)
  • That original commits still exist
  • Why commit IDs changed

Common Patterns

Pattern 1: Feature Branch Workflow

1. Branch from main
2. Develop feature
3. Rebase onto main before merging
4. Fast-forward merge into main

Pattern 2: Keep Branch Current

While developing:
- Regularly rebase onto main
- Ensures compatibility
- Reduces final merge conflicts

Rebase Interactive Options

While not in basic levels, interactive rebase supports:
  • pick - Use the commit
  • reword - Change commit message
  • edit - Modify commit
  • squash - Combine with previous
  • drop - Remove commit
  • Merging - Alternative integration strategy
  • Branching - Creating branches to rebase
  • Commits - Understanding what gets copied

Next Steps

After mastering rebase:
  1. Learn when to use rebase vs. merge
  2. Practice interactive rebase for commit cleanup
  3. Understand remote branch implications
  4. Explore advanced rebase scenarios

Build docs developers (and LLMs) love