This lesson on Interactive Rebase is hands-on and example-driven. You will learn how to safely rewrite local Git history using interactive rebase (git rebase -i) to condense multiple small commits into a single, clean, and descriptive commit. This skill is essential for maintaining a professional and readable repository history before merging feature branches.
What You'll Be Able To Do
- Isolate destructive Git operations by creating ephemeral branches for safe rollback.
- Determine the correct range of commits to target using
HEAD~nsyntax. - Apply
pickandsquashinstructions within the interactive rebase editor. - Write a single, high-quality commit message summarizing the work of multiple squashed commits.
- Verify the integrity of the code base after history rewriting using
git diff. - Condense a series of development commits into one cohesive commit for final merge.
Detailed Concept Walkthrough
1. History Assessment and Isolation
Before rewriting history, you must identify the target commits and create a temporary branch to isolate the destructive operation. This ensures the original history remains intact for easy rollback.
- Mechanism: Commands like
git shortlogandgit branch -avvhelp visualize the commit history and current branch structure, defining the scope of the rebase. - Best Practice: Always create a new, isolated branch derived from the feature branch before initiating
rebase -ito guarantee a safe rollback path. - Execution Flow: If the rebase fails or results in unwanted changes, you can simply delete the isolated branch and return to the original feature branch without losing work.
git checkout -b VB-9-rebase feature/original-branch
# Now perform rebase on VB-9-rebase
Key Takeaway: Isolate history rewriting operations on a temporary branch to guarantee a safe rollback path.
2. Executing Interactive Rebase
Interactive rebase opens an editor allowing you to define a new sequence of commits relative to a specified ancestor, enabling history modification. The command targets commits after the specified ancestor.
- Syntax Rule: The command
git rebase -i HEAD~ntargets the last 'n' commits, excluding the commitHEAD~nitself, which serves as the base. - Mechanism: Git pauses the rebase process and presents a list of commits in chronological order (oldest first) in your configured text editor.
- Under the Hood: Git temporarily saves the commits, applies the instructions (pick, squash, fixup, etc.), and then reapplies the modified commits sequentially, generating new commit SHAs.
git rebase -i HEAD~6 # Targets the last 6 commits for modification
Key Takeaway: Use
git rebase -i HEAD~nto define the exact range of commits you intend to modify or combine.
3. Squashing and Message Rewriting
Squashing combines multiple sequential commits into a single, unified commit, resulting in a cleaner, more linear project history, ideal for condensing 'work-in-progress' commits.
- Mechanism: Changing a commit instruction from
picktosquashtells Git to merge that commit's changes into the commit immediately preceding it in the interactive editor list. - Squash Directionality: A commit marked
squashalways collapses upwards into the commit listed directly above it. - Best Practice: The first commit in the interactive list must always be marked
pick; it serves as the base commit that absorbs all subsequent squashed commits. - Execution Flow: After saving the instructions, Git opens a second editor instance where you must write a single, descriptive commit message summarizing the combined work.
pick 1a2b3c4 Initial setup
squash 5d6e7f8 Fix typo in config
squash 9g0h1i2 Add logging feature
Key Takeaway: Squashing collapses commits upwards into the preceding
pickcommit, requiring a new, high-quality summary message.
Topics Covered in Interactive Rebase
- Assess History Scope (00:00 - 01:13) — Inspect the current commit history using
git shortlogto define the goal of the cleanup. - Create Safety Branch (01:15 - 01:48) — Check out a new, isolated branch derived from the feature branch to allow for easy rollback.
- Initiate Interactive Rebase (01:49 - 02:00) — Execute
git rebase -i HEAD~nto open the editor and target the specific range of commits. - Apply Squash Instructions (02:03 - 02:57) — Change the instruction from
picktosquashfor all commits that should be merged into the preceding commit. - Rewrite Commit Message (02:58 - 03:41) — Edit the second editor window to create a single, clean, and descriptive summary for the consolidated commit.
- Verify and Merge (03:49 - 05:10) — Use
git diffto confirm code integrity before merging the newly cleaned branch into the main target branch.
Git Cheat Sheet
-
git shortlog— Inspects commit history and authorshipgit shortlog -
git checkout -b <new-branch>— Creates and switches to a new isolated branchgit checkout -b rebase-safe-zone -
git rebase -i HEAD~n— Initiates interactive rebase on the last 'n' commitsgit rebase -i HEAD~4 -
pick— Keeps the commit and applies it to the historypick 1a2b3c4 Feature start -
squash— Merges commit changes into the previous commitsquash 5d6e7f8 WIP changes -
git diff <original> <rebased>— Verifies code integrity between two branchesgit diff feature/original VB-9-rebase
Comparison Table
| Instruction | Effect on Commit | Message Handling |
|---|---|---|
| pick | Retains the commit | Original message retained |
| squash | Merges into preceding commit | Requires new combined message |
| rebase -i | Rewrites history | Creates new commit SHAs |
Common Pitfalls
- Mistake: Rebase directly on the main branch or a shared branch. Avoid: Use a temporary isolated branch and only rebase local, unpushed commits.
- Mistake: Marking the first commit in the interactive list as 'squash'. Avoid: The first commit must always be marked 'pick' to serve as the base.
- Mistake: Forgetting to verify the code integrity after rebase.
Avoid: Run
git diff [original] [rebased]to ensure an empty result. - Mistake: Leaving the auto-generated list of commit messages. Avoid: Delete the list and write a single, descriptive summary message.
FAQs
- Why is interactive rebase considered a destructive action? It rewrites history by creating entirely new commit SHAs, which can cause conflicts if the history has already been shared with others.
- How does the 'squash' directionality work? A commit marked 'squash' collapses its changes upwards into the commit listed immediately before it in the interactive editor.
- What is the purpose of running
git diffafter rebase? It validates that the history cleanup did not accidentally alter the final code state, ensuring the rebased branch is functionally identical to the original. - Can I use rebase to combine commits that are not sequential? Yes, but you must use the rebase editor to reorder the commits first so that the ones you want to squash are adjacent.