DaleSchool

Rebase Basics

Beginner25min

Learning Objectives

  • Visually understand the difference between rebase and merge results
  • Update a branch to the latest state with git rebase
  • Edit or squash commits with interactive rebase

Working Code

Example 1: Creating a behind-the-times branch

git init
echo "v1" > file.txt
git add file.txt
git commit -m "feat: add file"

# Create a feature branch
git checkout -b feature-work
echo "feature work" > feature.txt
git add feature.txt
git commit -m "feat: add feature work"

Add a new commit to main:

git checkout main
echo "main extra work" >> file.txt
git add file.txt
git commit -m "feat: add extra work on main"

Check history:

git log --oneline --graph --all

Output:

* a1b2c3d (HEAD -> main) feat: add extra work on main
| * e4f5g6h (feature-work) feat: add feature work
|/
* f7g8h9i feat: add file

Example 2: Rebasing onto the latest main

git checkout feature-work
git rebase main

Output:

Successfully rebased and updated refs/heads/feature-work.

Check history:

git log --oneline --graph --all

Output:

* j0k1l2m (HEAD -> feature-work) feat: add feature work
* a1b2c3d (main) feat: add extra work on main
* f7g8h9i feat: add file

The history is now linear. The feature commits sit on top of main.

Git 터미널

Create two branches, commit on each, and check git log --oneline --graph --all.

user@daleschool:~/myproject$

Try It Yourself

merge vs rebase: comparing results

Given the same starting point, here's how merge and rebase differ:

Starting state:
A - B - C (main)
      \
       D - E (feature)

After merge:
A - B - C - M (main, merge commit)
      \   /
       D - E (feature)

After rebase:
A - B - C (main)
         \
          D' - E' (feature, rebased)

Rebase replays the feature commits on top of main. The content is the same but the hashes change (D -> D').

Interactive rebase: tidying up commits

# Create several work-in-progress commits
echo "1" >> work.txt && git add work.txt && git commit -m "wip: work in progress 1"
echo "2" >> work.txt && git add work.txt && git commit -m "wip: work in progress 2"
echo "3" >> work.txt && git add work.txt && git commit -m "feat: feature complete"

Interactively rebase the last 3 commits:

git rebase -i HEAD~3

The editor opens:

pick a1b2c3d wip: work in progress 1
pick e4f5g6h wip: work in progress 2
pick i7j8k9l feat: feature complete

Squash the wip commits together:

pick a1b2c3d wip: work in progress 1
squash e4f5g6h wip: work in progress 2
pick i7j8k9l feat: feature complete

After saving, a message editor opens:

# Combined commit messages
wip: work in progress 1
wip: work in progress 2

Replace with a clean message:

wip: initial implementation

After saving, the 3 commits become 2.

Handling conflicts during rebase

git rebase main   # Conflict occurs

Output:

CONFLICT (content): Merge conflict in file.txt
error: could not apply a1b2c3d...
hint: Resolve all conflicts manually...
# Resolve the conflict
nano file.txt   # Edit

git add file.txt
git rebase --continue   # Move on to the next commit

# Or abort the rebase entirely
git rebase --abort

"Why?" -- rebase vs merge

Both combine branches, but the resulting history differs.

mergerebase
HistoryPreserves branch structureLinear and clean
SafetyAlways safeRisky on shared branches
ConflictsOncePer commit
Use casePR merges, collaborationCleaning up personal branches

Golden rule: Never rebase shared branches that have already been pushed (main, develop).

Why? Rebase changes commit hashes. If teammates have already fetched those commits, their history will conflict with yours.

# Safe rebase patterns

# 1. Clean up unpushed local branches
git rebase -i HEAD~5

# 2. Update local feature to latest main (before pushing)
git rebase main

# 3. Merge PRs through GitHub (merge commit or squash merge)

Common Mistakes

Mistake 1: Rebasing a pushed branch

git push origin feature-login   # Already pushed
git rebase main                 # Changes commit hashes
git push                        # Error!
# error: failed to push some refs...

# Force push (causes problems for teammates!)
git push --force   # Never do this on shared branches!

Mistake 2: Rebasing from the wrong branch

# Wrong: rebasing feature onto main FROM main
git checkout main
git rebase feature-login   # main's history gets rewritten!

# Correct: rebase from the feature branch
git checkout feature-login
git rebase main

Mistake 3: Panicking during interactive rebase

git rebase -i HEAD~3
# Accidentally saved something wrong in the editor

# You can always abort
git rebase --abort   # Fully restores the original state

Deep Dive

Full interactive rebase command list

Commands available for each commit in the editor:

CommandShortDescription
pickpKeep the commit as-is
rewordrEdit the commit message only
editeEdit the commit content
squashsMerge into previous commit (combine messages)
fixupfMerge into previous commit (discard message)
dropdDelete the commit
execeRun a shell command between commits
git pull --rebase: cleaner history
# Default git pull = fetch + merge (creates merge commits)
git pull

# git pull --rebase = fetch + rebase (linear history)
git pull --rebase

# Set as default
git config --global pull.rebase true

If your team prefers clean history, set pull.rebase true.

Squash merge: tidying up when merging PRs

Three ways to merge a PR:

# 1. Merge commit: preserve all commits + merge commit
git merge --no-ff feature-branch

# 2. Squash merge: combine all commits into one on main
git merge --squash feature-branch
git commit -m "feat: integrate feature"

# 3. Rebase merge: linear history on main
git rebase main && git checkout main && git merge feature-branch

GitHub lets you restrict allowed merge methods in PR settings.

  1. Create a feature branch and add 3 commits.
  2. Add a new commit to main as well.
  3. From the feature branch, run git rebase main and check history with git log --oneline --graph --all.
  4. Add 2 wip: commits and 1 feat: commit on feature, then use git rebase -i HEAD~3 to squash the wip commits.
Git 터미널

Create two branches, commit on each, and visualize the diverging history with git log --oneline --graph --all.

user@daleschool:~/myproject$

Why should you not rebase a shared branch (one that's already been pushed)?