Skip to content
7 min read·Lesson 9 of 10

Rewriting History: Rebase, Squash, and Stash

Learn how to keep a clean Git history using rebase, interactive rebase, squash commits, cherry-pick, and stash — and when it is safe to rewrite history.

Git gives you the power to reshape history — to clean up messy work-in-progress commits before sharing them, or to integrate changes from another branch cleanly. This lesson covers the tools for that: rebase, interactive rebase, stash, and cherry-pick.

git rebase

Rebase replays your branch's commits on top of another commit, giving your branch a new "base." The result is a linear history — as if you had started your branch from the latest version of main:

Before rebase:
  main:    A -- B -- C
                  feature:       D -- E

git switch feature
git rebase main

After rebase:
  main:    A -- B -- C
                        feature:             D' -- E'   (new commits — SHA changed)
git switch feature/my-feature
git fetch origin
git rebase origin/main

Important: Rebase rewrites commit SHAs. If you have already pushed the branch to a remote, you will need to force-push. Use --force-with-lease to avoid overwriting changes from others:

git push --force-with-lease origin feature/my-feature

The golden rule: Never rebase a branch that other people are working from. Rebase is safe for your own feature branches before they are merged — not for main or shared branches.

Interactive Rebase

Interactive rebase (git rebase -i) opens an editor showing the last N commits and lets you edit each one:

# Interactively edit the last 4 commits
git rebase -i HEAD~4

The editor shows:

pick a1b2c3d Add login form
pick d4e5f6g WIP
pick h7i8j9k Fix typo
pick l0m1n2o Add form validation

Change the action word before each commit:

CommandAction
pickKeep this commit as-is
rewordKeep the commit but edit the message
editPause to amend the commit's content
squashMerge this commit into the previous one (combine messages)
fixupMerge into previous, discard this commit's message
dropDelete this commit entirely

A common use: squash all the "WIP" and "fix typo" commits into a single clean commit before opening a PR.

git stash

Stash saves your current working tree and staging area onto a stack and reverts to a clean state. Useful when you need to switch branches mid-work without making a messy commit:

# Stash all uncommitted changes
git stash

# Stash with a descriptive message
git stash push -m "half-finished login refactor"

# List all stashes
git stash list

# Apply the most recent stash and remove it from the stack
git stash pop

# Apply a specific stash without removing it
git stash apply stash@{2}

# Delete all stashes
git stash clear

git cherry-pick

Cherry-pick applies the changes from a specific commit onto the current branch — without merging the entire branch. Useful for backporting a bug fix to a release branch:

# Apply commit abc1234 to the current branch
git cherry-pick abc1234

# Apply a range of commits
git cherry-pick abc1234..def5678

Like rebase, cherry-pick creates a new commit (new SHA) with the same changes. Use it sparingly — frequent cherry-picking can cause divergence that is painful to reconcile later.

git amend

# Fix the message of the most recent commit
git commit --amend -m "Correct commit message"

# Add forgotten staged changes to the most recent commit
git add forgotten-file.ts
git commit --amend --no-edit

Like rebase, --amend rewrites the most recent commit — only use it before pushing.

When Is Rewriting History Safe?

  • Safe: Rewriting commits on your own local or remote feature branch that no one else has pulled
  • Unsafe: Rewriting commits on main, or any branch shared with teammates who have already cloned those commits
  • If you must force-push a shared branch (e.g., fixing a leaked secret), communicate clearly with all affected developers

Key Takeaways

  • git rebase replays commits on top of a new base commit, resulting in a linear history.
  • Interactive rebase (git rebase -i) lets you reorder, squash, edit, or drop individual commits.
  • The golden rule of rebasing: never rebase commits that have been pushed to a shared branch.
  • git stash temporarily saves working tree changes so you can switch context without committing.
  • git cherry-pick applies a specific commit from another branch to the current branch.

Test your knowledge

Try exam-style practice questions to reinforce what you've learned.

Practice Questions →