Lesson 95 of 12135 min read

Practical Exercise: Use Interactive Rebase to Clean Up a Messy Feature Branch Before a PR

Apply Module 7's interactive rebase skills in one realistic exercise: transform a messy, exploratory commit history into a clean one, ready for review.

Author: CodersNexus

Practical Exercise: Use Interactive Rebase to Clean Up a Messy Feature Branch Before a PR

This capstone exercise brings together the module's most practically valuable skill — interactive rebase — into the exact real-world scenario it's most commonly used for: taking a messy, exploratory feature branch, full of typo fixes and 'wip' commits made during genuine development, and transforming it into a small number of clean, well-described commits, ready for a reviewer's attention, directly applying Module 5's PR best practices at the level of individual commit quality.

Learning Objectives

  • Simulate a realistic messy commit history reflecting genuine, exploratory development.
  • Use interactive rebase to squash, fixup, reword, and reorder these commits.
  • Verify the resulting clean history before pushing and opening a pull request.
  • Apply the golden rule of rebasing correctly, confirming the branch hasn't been shared yet.

Key Terms to Know Before This Interactive Rebase Practical Exercise

  • Messy history: A commit history reflecting the natural, exploratory process of development — typo fixes, 'wip' commits, reverted experiments — genuinely useful during development but not meaningful as permanent record.
  • Clean history: A commit history reorganized into a small number of well-described, logically grouped commits, each representing one meaningful, reviewable change.
  • Pre-PR cleanup: The practice of interactively rebasing a local feature branch to improve its commit history before opening a pull request for review.

How to Clean Up a Messy Branch With Interactive Rebase, Step by Step

**Step 1: Simulate a realistic messy branch.** Create a new feature branch and make a series of commits reflecting genuine, exploratory development — including some that wouldn't belong in permanent history:

```
git switch -c feature/user-profile-page
# ... create profile.js with initial content ...
git commit -m "wip: start user profile page"
# ... fix a typo ...
git commit -m "fix typo"
# ... add the actual core feature logic ...
git commit -m "add avatar upload functionality"
# ... address a self-review issue ...
git commit -m "fix eslint warning"
# ... add tests ...
git commit -m "add tests for avatar upload"
```

This produces five commits, only some of which are genuinely meaningful as permanent history — `wip: start user profile page` and `fix typo` are exactly the kind of exploratory noise interactive rebase is designed to clean up.

**Step 2: Confirm the golden rule applies safely here.** Before rebasing, verify this branch is still local-only and hasn't been pushed or shared with anyone (this module's earlier lesson on the golden rule of rebasing):

```
git log origin/main..HEAD --oneline
# (if this branch has never been pushed, ALL its commits appear here — confirms it's safe to rebase)
```

**Step 3: Launch an interactive rebase covering all five commits.**

```
git rebase -i HEAD~5
```

**Step 4: Edit the todo list to clean things up.** The default (oldest first) list:

```
pick a1b2c3d wip: start user profile page
pick 9f8e7d6 fix typo
pick 3c4d5e6 add avatar upload functionality
pick 7g8h9i0 fix eslint warning
pick 1j2k3l4 add tests for avatar upload
```

Edit it to:

```
pick a1b2c3d wip: start user profile page
fixup 9f8e7d6 fix typo
reword 3c4d5e6 add avatar upload functionality
fixup 7g8h9i0 fix eslint warning
pick 1j2k3l4 add tests for avatar upload
```

**Step 5: Save and let Git carry out the plan.** The `fixup` for 'fix typo' silently folds it into the first commit with no separate message. The `reword` for the core feature commit pauses to let you write a more complete, descriptive message (e.g., `feat: add avatar upload functionality to user profile page`), into which the `fixup` for 'fix eslint warning' also gets silently folded, since it's the immediately preceding commit in the plan.

**Step 6: Optionally reword the very first commit too**, since `wip: start user profile page` still isn't a great permanent message — you could further clean this up (e.g., via an additional `reword`) to something like `feat: scaffold user profile page structure`.

**Step 7: Verify the resulting clean history.**

```
git log --oneline
# 1j2k3l4 test: add tests for avatar upload
# a1b2c3d feat: add avatar upload functionality to user profile page
# 9f8e7d6 feat: scaffold user profile page structure
```

Five messy commits have become three clean, well-described ones.

**Step 8: Push and open the pull request.** Since this branch was never previously pushed, the first push proceeds normally with no force required (this module's golden rule lesson):

```
git push -u origin feature/user-profile-page
```

The resulting pull request (Module 5) now shows a small, clearly described commit history that a reviewer can quickly and confidently understand — directly serving the small-focused-PR philosophy from Module 5's best practices lesson, now applied at the level of individual commit quality within the PR, not just its overall scope.

Before and After Interactive Rebase Cleanup: Visual Walkthrough

Draw a BEFORE/AFTER comparison. BEFORE: five commit boxes stacked vertically: 'wip: start user profile page', 'fix typo', 'add avatar upload functionality', 'fix eslint warning', 'add tests for avatar upload' — captioned 'Messy, exploratory history — genuinely useful during development, not meaningful as permanent record.' An arrow labeled 'git rebase -i HEAD~5 (fixup + reword)' points to AFTER: three clean commit boxes: 'feat: scaffold user profile page structure', 'feat: add avatar upload functionality to user profile page', 'test: add tests for avatar upload' — captioned 'Clean, reviewable history — ready for a pull request.'

Cleanup Exercise Steps: Quick Reference Table

StepCommand / ActionPurpose
1. Create messy history5 commits reflecting exploratory developmentSimulates a realistic pre-cleanup scenario
2. Confirm golden rule safetygit log origin/main..HEAD --onelineVerifies the branch is local-only, safe to rebase
3-4. Launch + edit interactive rebasegit rebase -i HEAD~5, edit todo list actionsPlans the fixup/reword/pick actions for each commit
5-6. Execute the planSave the editor; provide new messages when promptedGit folds fixups silently, opens editor for reword
7. Verify clean resultgit log --onelineConfirms 5 messy commits became 3 clean ones
8. Push and open PRgit push -u origin <branch>First push — no force needed, since never previously shared

Cleaning Up the Branch: Command Syntax

# Step 1: Create a messy, realistic history
git switch -c feature/user-profile-page
echo "// profile page" > profile.js
git add profile.js && git commit -m "wip: start user profile page"
echo "// fixed" >> profile.js
git add profile.js && git commit -m "fix typo"
echo "function uploadAvatar() {}" >> profile.js
git add profile.js && git commit -m "add avatar upload functionality"
echo "// lint fix" >> profile.js
git add profile.js && git commit -m "fix eslint warning"
echo "// tests" > profile.test.js
git add profile.test.js && git commit -m "add tests for avatar upload"

# Step 2: Confirm safe to rebase (never pushed)
git log origin/main..HEAD --oneline

# Step 3: Launch interactive rebase
git rebase -i HEAD~5
# Edit the todo list: pick / fixup / reword / fixup / pick (as described above)
# Provide improved messages when prompted for the 'reword' actions

# Step 7: Verify
git log --oneline

# Step 8: Push (first push — no force needed)
git push -u origin feature/user-profile-page

Breaking Down the Cleanup Exercise Example

This sequence recreates the complete, realistic pre-PR cleanup workflow: building a genuinely messy five-commit history reflecting natural development (including a typo fix and a lint fix that don't deserve their own permanent entries), confirming the branch is safe to rebase per the golden rule, then using interactive rebase's `fixup` and `reword` actions to consolidate it down to three clean, well-described commits. The final push proceeds normally with no force flag needed, since — critically — this cleanup happened entirely on a branch that was never previously pushed or shared, exactly the safe use case the golden rule describes.

How This Cleanup Workflow Mirrors Real Pre-PR Practices

  • This exact fixup-and-reword cleanup pattern is one of the most common, routine uses of interactive rebase among professional developers, performed on nearly every non-trivial feature branch before it's proposed for review.
  • Some teams' code review culture explicitly expects a cleaned-up commit history as a courtesy to reviewers, with interactive rebase being the standard tool for meeting that expectation before requesting review.
  • Technical interviews sometimes specifically ask candidates to demonstrate interactive rebase, since it's considered a genuine marker of intermediate-to-advanced Git fluency beyond just the basic commands.
  • Engineering onboarding materials at many companies include this exact 'clean up your branch before opening a PR' guidance as a standard, expected part of the team's development workflow.

Interactive Rebase Cleanup Interview Questions and Answers

Q1. Walk through how you would clean up a messy feature branch's commit history before opening a pull request.

First confirm the branch hasn't been pushed yet (or if it has, that no one has pulled it), consistent with the golden rule of rebasing. Then run git rebase -i targeting the base commit before your branch's work began, and in the resulting todo list, use fixup for small correction commits that don't need their own message, reword for commits with unclear messages, and reorder if grouping related changes differently would tell a clearer story. Save, let Git carry out the plan, providing new messages when prompted, then verify the resulting clean history with git log before pushing.

Q2. Why is it safe to interactively rebase the branch in this exercise, but not necessarily in every situation?

Because this branch has never been pushed or shared with anyone — confirmed by checking that all its commits appear in the difference between origin/main and HEAD. Per the golden rule of rebasing, it's only safe to rewrite commits that exist solely on your own machine; rebasing a branch already pulled by a collaborator would create diverged history.

Q3. What is the practical benefit of this cleanup for the eventual pull request reviewer?

A reviewer sees a small number of clear, well-described commits directly reflecting meaningful changes, rather than a noisy history full of typo fixes and 'wip' commits. This makes the review faster and more thorough, directly supporting the same underlying goal as Module 5's small-focused-PR guidance, now applied at the level of individual commit quality.

Interactive Rebase Cleanup Quiz: Test Your Understanding

1. In this exercise, why is it confirmed safe to rebase the feature branch before cleanup begins?

  1. Because rebase is always safe under any circumstances
  2. Because the branch has never been pushed or shared with anyone, consistent with the golden rule of rebasing
  3. Because the branch contains fewer than 10 commits
  4. Because interactive rebase never causes conflicts

Answer: B. Because the branch has never been pushed or shared with anyone, consistent with the golden rule of rebasing

Explanation: The golden rule of rebasing specifically permits rewriting commits that exist solely on your own machine; this exercise confirms that safety condition before proceeding with the interactive rebase.

2. In this exercise, which interactive rebase action is used to silently fold the 'fix typo' commit into the preceding one?

  1. pick
  2. fixup
  3. drop
  4. squash

Answer: B. fixup

Explanation: fixup combines a commit with the one before it while discarding its own message entirely, exactly appropriate for a small correction commit like 'fix typo' that doesn't need its own separate explanation in the final history.

3. What is the practical benefit of cleaning up commit history with interactive rebase before opening a pull request?

  1. It makes the code run faster
  2. It gives reviewers a small number of clear, well-described commits, making review faster and more thorough
  3. It automatically merges the pull request
  4. It prevents any future commits from being added to the branch

Answer: B. It gives reviewers a small number of clear, well-described commits, making review faster and more thorough

Explanation: A clean, well-organized commit history lets a reviewer quickly understand exactly what changed and why, directly supporting faster, more confident code review.

Common Mistakes When Cleaning Up a Branch Before a PR

  • Rebasing a branch that's already been pushed and potentially pulled by a collaborator, without first confirming it's still safe per the golden rule.
  • Confusing fixup and squash, ending up with an unwanted extra message-editing prompt (squash) when a silent fold (fixup) was actually intended.
  • Forgetting the interactive rebase todo list is ordered oldest-to-newest, misplacing actions relative to git log's usual newest-first ordering.
  • Skipping the verification step (git log --oneline) after the rebase, and pushing a history that doesn't actually look the way it was intended to.

Interactive Rebase Cleanup: Exam-Ready Quick Notes

  • Golden rule check first: git log origin/main..HEAD --oneline confirms the branch is local-only, safe to rebase.
  • git rebase -i HEAD~5: launches interactive rebase covering the last 5 commits.
  • fixup: silently folds a commit (like a typo fix) into the preceding one. reword: keeps content, edits message.
  • First push after cleanup (never previously shared): no force flag needed.

Interactive Rebase Cleanup: Key Takeaways

  • This exercise demonstrates the single most common, practically valuable real-world use of interactive rebase: cleaning up a branch before requesting review.
  • Confirming the golden rule of rebasing applies (branch never pushed) is an essential first step before any cleanup rebase.
  • A small number of clean, well-described commits directly makes a reviewer's job faster and more effective, extending Module 5's PR best practices to the level of individual commits.

Frequently Asked Questions About Cleaning Up a Branch Before a PR

Q1. Why would I want to clean up my commit history before opening a pull request?

A clean, well-organized history with a small number of clearly described commits is much easier and faster for a reviewer to understand and evaluate, compared to a noisy history full of typo fixes and 'work in progress' commits made during natural, exploratory development.

Q2. How do I know it's safe to rebase my feature branch's history?

Confirm the branch hasn't been pushed or shared with anyone yet, per the golden rule of rebasing — for example, by checking that all its commits appear in the difference between origin/main and your current branch (git log origin/main..HEAD --oneline).

Q3. What interactive rebase actions are most useful for this kind of cleanup?

fixup is ideal for small correction commits (like typo fixes) that don't need their own separate message — it silently folds them into the previous commit. reword is useful for improving an unclear commit message without changing its actual content.

Q4. How do I verify my cleanup actually worked as intended?

Run git log --oneline after the rebase completes to review the resulting commit history, confirming it now shows the smaller number of clean, well-described commits you intended, before pushing.

Q5. Do I need to force-push after cleaning up my branch with interactive rebase?

Only if the branch had already been pushed before the rebase. If, as in this exercise, the branch was never previously pushed, the first push proceeds completely normally with no force flag required.

Summary

This capstone exercise applies interactive rebase to its most common, practically valuable real-world use case: transforming a messy, exploratory feature branch's commit history into a clean, reviewable one before opening a pull request. After simulating a realistic five-commit history (including a typo fix and a lint fix that don't deserve their own permanent record), the exercise confirms the golden rule of rebasing applies safely by checking that the branch has never been pushed. `git rebase -i HEAD~5` launches the interactive rebase, and editing the todo list's actions — using `fixup` to silently fold small correction commits into the ones before them, and `reword` to improve unclear messages — consolidates five messy commits down to three clean, well-described ones. After verifying the result with `git log --oneline`, the branch is pushed for the first time with no force flag needed, since it was never previously shared, and the resulting pull request presents reviewers with a small, clear commit history — directly extending Module 5's small-focused-PR philosophy to the level of individual commit quality.

Frequently Asked Questions

A clean, well-organized history with a small number of clearly described commits is much easier and faster for a reviewer to understand and evaluate, compared to a noisy history full of typo fixes and 'work in progress' commits made during natural, exploratory development.

Confirm the branch hasn't been pushed or shared with anyone yet, per the golden rule of rebasing — for example, by checking that all its commits appear in the difference between origin/main and your current branch (git log origin/main..HEAD --oneline).

fixup is ideal for small correction commits (like typo fixes) that don't need their own separate message — it silently folds them into the previous commit. reword is useful for improving an unclear commit message without changing its actual content.

Run git log --oneline after the rebase completes to review the resulting commit history, confirming it now shows the smaller number of clean, well-described commits you intended, before pushing.

Only if the branch had already been pushed before the rebase. If, as in this exercise, the branch was never previously pushed, the first push proceeds completely normally with no force flag required.