Git & GitHub

Rebasing

13 min Lesson 11 of 35

Rebasing

Rebasing is a powerful Git feature that allows you to rewrite commit history by moving or combining commits. In this lesson, we'll explore what rebasing is, when to use it, and how it differs from merging.

What is Rebasing?

Rebasing is the process of moving or combining a sequence of commits to a new base commit. Unlike merging, which creates a new commit with two parents, rebasing rewrites the project history by creating new commits for each commit in the original branch.

Key Concept: Rebasing changes the commit history by rewriting it, making it appear as if you created your commits from a different starting point.

Basic Rebase Command

The basic syntax for rebasing is:

# Rebase current branch onto another branch git rebase <base-branch> # Example: Rebase feature branch onto main git checkout feature-branch git rebase main

How Rebasing Works

Here's what happens during a rebase:

1. Git finds the common ancestor of current branch and target branch 2. Git saves all commits made since the common ancestor 3. Git resets the current branch to the target branch 4. Git applies each saved commit one by one on top of target branch 5. Each commit gets a new SHA hash (new commit ID)
Tip: Think of rebasing as "replaying" your commits on top of a different starting point, creating a linear history.

Visual Example: Rebase vs Merge

Before: C3 (feature) / C1--C2 (main) After Merge: C3 (feature) / \ C1--C2--C4 (main) ← merge commit After Rebase: C1--C2--C3' (feature) ← rebased commit (main)

Interactive Rebase

Interactive rebase is one of Git's most powerful features, allowing you to edit, reorder, squash, or delete commits:

# Start interactive rebase for last 3 commits git rebase -i HEAD~3 # Interactive rebase onto a branch git rebase -i main

This opens an editor with options:

pick abc1234 Add login feature pick def5678 Fix typo in login pick ghi9012 Update documentation # Commands: # p, pick = use commit # r, reword = use commit, but edit message # e, edit = use commit, but stop for amending # s, squash = meld into previous commit # f, fixup = like squash, but discard message # d, drop = remove commit

Squashing Commits

Squashing combines multiple commits into one, creating a cleaner history:

# Change in interactive rebase editor: pick abc1234 Add login feature squash def5678 Fix typo in login squash ghi9012 Update documentation # Results in one commit with combined changes
Use Case: Squash commits before merging a feature branch to keep the main branch history clean and focused on complete features rather than incremental changes.

Rebase vs Merge: When to Use Each

Use REBASE when: ✓ Working on a local feature branch ✓ Want to maintain a linear project history ✓ Updating feature branch with latest main changes ✓ Cleaning up commits before pushing ✓ Working alone on a branch Use MERGE when: ✓ Integrating completed features into main branch ✓ Working on public/shared branches ✓ Want to preserve exact history of changes ✓ Multiple people working on same branch ✓ Want to see when features were integrated

The Golden Rule of Rebasing

Critical Rule: Never rebase commits that have been pushed to a public repository and that others may have based work on. Rebasing rewrites history, which can cause serious issues for collaborators.

Safe rebasing practices:

✓ Rebase local commits that haven't been pushed ✓ Rebase your own feature branches ✓ Rebase before creating a pull request ✗ Never rebase the main/master branch ✗ Never rebase commits others are working on ✗ Never rebase public release branches

Resolving Rebase Conflicts

Conflicts during rebase are resolved one commit at a time:

# If conflict occurs during rebase: # 1. Fix conflicts in affected files git status # See conflicted files # 2. Stage resolved files git add <resolved-files> # 3. Continue rebase git rebase --continue # Or abort if needed git rebase --abort
Tip: During a rebase, you may need to resolve the same conflict multiple times if it appears in different commits. Be patient and resolve each carefully.

Practical Rebase Workflow

Here's a common workflow for keeping a feature branch up to date:

# You're working on feature-branch git checkout feature-branch # Fetch latest changes from remote git fetch origin # Rebase your branch onto latest main git rebase origin/main # If conflicts occur, resolve and continue # Once complete, force push (only if previously pushed) git push --force-with-lease origin feature-branch

Rewriting Commit Messages

Use reword to change commit messages without changing content:

# Start interactive rebase git rebase -i HEAD~3 # In editor, change pick to reword: reword abc1234 Add login feature pick def5678 Fix typo pick ghi9012 Update docs # Git will pause at each reword commit # Edit the message and save

Editing Past Commits

Use edit to modify the content of past commits:

# Start interactive rebase git rebase -i HEAD~3 # Change pick to edit for commits to modify edit abc1234 Add login feature pick def5678 Fix typo # Git stops at the edit commit # Make your changes git add <files> git commit --amend git rebase --continue

Dropping Commits

Remove unwanted commits from history:

# In interactive rebase editor: pick abc1234 Add feature drop def5678 Accidentally committed secrets pick ghi9012 Update docs # Or simply delete the line
Security Note: If you accidentally committed secrets, dropping the commit isn't enough - the secrets are still in Git history. You need to use git filter-branch or BFG Repo-Cleaner to completely remove them.

Rebase Onto a Different Branch

You can rebase onto any branch or commit:

# Rebase current branch onto develop git rebase develop # Rebase feature-a onto feature-b git checkout feature-a git rebase feature-b # Rebase onto a specific commit git rebase abc1234

Abort and Skip Options

# Abort rebase and return to original state git rebase --abort # Skip the current commit (if causing issues) git rebase --skip # Continue after resolving conflicts git rebase --continue

Practice Exercise:

Scenario: You have a feature branch with 3 messy commits that you want to clean up before merging.

# Create a practice repo git init rebase-practice cd rebase-practice # Create some commits echo "Feature v1" > feature.txt git add feature.txt git commit -m "Add feature" echo "Feature v2" >> feature.txt git commit -am "Fix typo" echo "Feature v3" >> feature.txt git commit -am "Another fix" # Now squash the 3 commits into one git rebase -i HEAD~3 # In editor, change to: # pick (first commit) # squash (second commit) # squash (third commit) # Save and edit the combined commit message # View the result git log --oneline

Challenge: Practice splitting a commit by using 'edit' command, then git reset HEAD^, and making two separate commits.

Common Rebase Pitfalls

Pitfall 1: Rebasing pushed commits → Solution: Only rebase local commits Pitfall 2: Losing commits during rebase → Solution: Use git reflog to recover Pitfall 3: Complex merge conflicts → Solution: Abort and use merge instead Pitfall 4: Forgetting to force-push after rebase → Solution: Use --force-with-lease for safety

Advanced: Autosquash

Git can automatically squash fixup commits:

# Create a fixup commit for a previous commit git commit --fixup abc1234 # Later, automatically squash all fixups git rebase -i --autosquash main

Summary

In this lesson, you learned:

  • Rebasing moves commits to a new base, rewriting history
  • Interactive rebase allows editing, squashing, and reordering commits
  • Use rebase for local branches, merge for public branches
  • Never rebase commits that others have based work on
  • Resolve rebase conflicts one commit at a time
  • Squashing creates cleaner, more focused commit history
  • Use --force-with-lease when pushing rebased branches
Next Up: In the next lesson, we'll explore remote repositories and learn how to work with them effectively!

ES
Edrees Salih
18 hours ago

We are still cooking the magic in the way!