Git: stash, cherry-pick & rebase
Real work is messy. You're halfway through something when an urgent fix comes in. A teammate has the one commit you need, buried in a branch full of unfinished work. And main has moved on while you worked on your branch. Three commands handle all of that: stash, cherry-pick and rebase.
You will learn
- Park unfinished work with
git stashand get it back withstash pop - Copy one commit to another branch with
git cherry-pick - Bring your branch up to date with
git rebase, and fix a conflict halfway through - Rebase or merge? And the rule for when not to rebase
Stash: a pocket for unfinished work
Git won't let you switch branches if that would overwrite changes you haven't committed. You could make a messy “WIP” commit, but stash is tidier. It saves your changes away and gives you a clean folder:
git stash # save changes to tracked files, clean the folder git stash -u # …and new (untracked) files too git stash push -m "gallery photos" # with a name, so you remember what it was git stash list # stash@{0} is the newest git stash pop # put the newest back, and delete it from the stash git stash apply # put it back, but keep a copy in the stash
Stashes are local (they're never pushed) and easy to forget. Pop them soon, and check git stash list now and then.
Cherry-pick: copy one commit
Sometimes you need one commit from another branch, not the whole branch. Maybe it's a bug fix that main needs today, while the rest of the branch isn't ready. cherry-pick copies that commit onto the branch you're on:
git log --oneline priya-wip # find the commit you want git switch main git cherry-pick 3f9a1c2 # a new commit on main, with the same change and message
The copy gets a new hash, because it has a different parent. When the original branch is merged later, git notices the change is already there.
Rebase: replay your work on top
You started a branch from main. Since then, other people's work has landed on main. You can bring your branch up to date two ways:
| Question | git merge main | git rebase main |
|---|---|---|
| What it does | Adds a merge commit that joins the two lines | Lifts your commits off and replays them, one by one, on top of the newest main |
| History looks like | A fork and a join, exactly as it happened | One straight line, as if you started today |
| Your commits | Unchanged | Rewritten: same changes, new hashes |
| Safe on a shared branch? | Yes | No: only for commits nobody else has |
Before: After git rebase main (on gallery):
main A───B───C───J main A───B───C───J
\ \
gallery G1───G2 gallery G1'───G2'
After a rebase, merging the branch into main is a simple fast-forward, and git log reads like a story.
Conflicts during a rebase
A rebase replays your commits one at a time, so a conflict stops it partway. The fix is the same as for a merge, with a different last step:
git statusshows the conflicted file. Open it, make it look right, and delete the<<<<<<<,=======and>>>>>>>lines.git add FILEmarks it as fixed.git rebase --continuecarries on with the next commit. (Notgit commit.)
Lost? git rebase --abort puts your branch back exactly as it was before you started. Note that during a rebase, HEAD (“ours”) is main's side, and your commit is the other side, the opposite of a merge.
Only rebase commits that nobody else has built on: your own branch, before you share it or while it's still just yours in a pull request. Never rebase main, or any branch your teammates pull from. If you must update a branch you've already pushed, push it with git push --force-with-lease, as lesson 5 shows.
Pull with rebase
git pull is a fetch plus a merge. If you'd rather replay your unpushed commits on top of what you pulled (no little merge commits), make it a fetch plus a rebase:
git pull --rebase # this once git config --global pull.rebase true # always
Real git can also rewrite a branch's commits with git rebase -i, an interactive rebase. It opens your editor with a list of commits so you can squash several into one, reword messages or drop some. It's handy for tidying a branch before a pull request. The playground doesn't have it, because it's all editor work.
Try it: the gallery branch 🖼️
You're on the gallery branch of the club website, halfway through adding photos. Priya's priya-wip branch has a fix for the club email address that main needs right now. And main has moved on since you started your branch.
Quick check
1. You're halfway through a change, and need to switch branches to fix something urgent. What's the tidy way?
✓ stash keeps your work safe, and reset --hard would throw it away.
2. A rebase stopped with a conflict. You fixed the file and ran git add. What's next?
✓ It commits the fixed step and replays the rest of your commits.
3. Which branch is it not OK to rebase?
✓ Rebasing rewrites commits. Everyone who already has the old ones would get a mess.