1. Courses
  2. Developer Foundations
  3. Git from the Inside
  4. Stop 5

40 minAdvanced

Rewriting history safely: rebase, squash, cherry-pick, stash

Git lets you tidy your commits before others see them: replay a branch on top of the latest main, squash five messy commits into two clear ones, copy one fix onto a release branch, or put half-done work aside. All of these make new commits instead of editing old ones, and that single fact tells you when they are safe.

By the end you can

  • Explain why rebase, amend and cherry-pick create new commit IDs
  • Choose between merge and rebase for a feature branch, and know the golden rule
  • Clean up a branch with interactive rebase, fixup! commits and --autosquash, and build an autosquash todo list in code
  • Push rewritten work with --force-with-lease and understand what it protects
  • Cherry-pick a hotfix onto a release branch and use git stash to switch tasks

The everyday picture

Before the weekly stock report goes to the regional manager, the store manager drafts it in a notebook. She crosses out lines, merges two notes about the same freezer, moves the urgent item to the top, and fixes a spelling mistake. Nobody minds. It is her draft. Once the report is filed at the regional office and others have read it, she never edits it again. If something was wrong, she sends a correction note that refers to the filed report.

That is the whole rule for this lesson. Your local, unshared commits are the draft: rewrite them as much as you like. Commits other people already have are the filed report: add a new commit on top instead (Undo anything shows git revert for exactly that).

Why "rewriting" always means "new commits"

A commit's ID is a fingerprint of its whole content: the snapshot, the author, the message, the time, and the ID of its parent (Inside the .git folder shows the raw bytes). Change any of these and you get a different ID. So Git cannot edit a commit in place. Every "rewrite" command makes new commits and moves the branch label to them:

  • git commit --amend makes a new commit to replace the last one, with your extra changes or new message.
  • git rebase takes your commits one by one and replays them on a new parent. Same changes, new parent, so new IDs.
  • git cherry-pick copies the change of one commit onto your current branch as a new commit.

The old commits are not destroyed immediately. They are simply no longer on any branch, and git reflog can find them for weeks (Undo anything). That safety net is why you can experiment with everything in this lesson. The danger is elsewhere. If a teammate already has the old commits, their history and yours now disagree, and Git treats your new commits as different work that happens to look the same.

Quick check

You run git commit --amend on a commit you have not pushed. What happens to the original commit?

Loading the rest of the lesson…