Lesson 3 of 5 in Rewriting History
Cherry-pick
Story: You don't need that whole timeline. Just one event from it, copied into yours.
Sometimes you need one commit from another branch, not the whole branch. A fix was made on a branch that isn't ready to merge. A useful commit is stuck in an experiment you're giving up. git cherry-pick copies the commits you name onto the branch you're on.
Copying a commit
First find the commit. git log --oneline redesign lists a branch's commits, newest first:
$ git log --oneline redesign
3e309cb (redesign) Try a wide layout
5d0b961 Fix a typo on the about page
303a5d5 Try an orange heading
...
Then, on the branch that needs it, name the commit:
$ git cherry-pick 5d0b961
[main 34434b6] Fix a typo on the about page
Date: Mon Jan 1 09:18:00 2024 +0000
1 file changed, 1 insertion(+), 1 deletion(-)
git applies that commit's change to your branch and commits it with the same message. The copy keeps the original's author and date, which is why git prints a Date: line.
You can name the commit by its id, as above, or relative to a branch, as you learned in Branching & Merging: redesign~1 is the commit just before redesign's newest. git cherry-pick redesign~1 does the same as git cherry-pick 5d0b961 here.
A copy, with a new id
Like a rebase, a cherry-pick makes a new commit: the same change and message, a new parent, and so a new id. The original stays on its branch, untouched. Now two commits in your repository hold the same change.
That's usually fine. If you later merge redesign into main, git sees that both sides made the same change, and merges it without a conflict. If you later rebase redesign onto main, git notices that main already has that change, and leaves your branch's copy out:
$ git rebase main
warning: skipped previously applied commit 5d0b961
hint: use --reapply-cherry-picks to include skipped commits
hint: Disable this message with "git config advice.skippedCherryPicks false"
Successfully rebased and updated refs/heads/redesign.
Several commits
git cherry-pick takes more than one commit. Name them oldest first: git copies them in the order you give, one new commit for each.
git cherry-pick main~2 main
In fact, a rebase is a series of cherry-picks: it copies each of your commits, in turn, onto the new base.
When a cherry-pick stops
A cherry-pick applies a change to a different starting point, so it can conflict, just like a merge or a rebase. git stops, marks the conflict in the file, and its hint names your choices: git cherry-pick --continue, --skip or --abort. This Terminal runs --continue and --abort.
Continue. Fix the file, stage it, and carry on:
git add style.css
git cherry-pick --continue
git opens the original's message in the edit pane. Save it as it is to keep it. git commits the copy, and the copy keeps the original's author. If you forget to stage the file, git refuses, as it does for a commit with a conflict in it. git commit finishes a cherry-pick of one commit too: git sees the cherry-pick in progress, and the edit pane opens with the original's message.
Abort. git cherry-pick --abort gives up. Your branch and your files go back to how they were before the cherry-pick, and the cherry-pick ends. Changes you hadn't committed in other files stay as they were. git reset --hard would end the cherry-pick too, but it throws those changes away.
And if the change is already on your branch, there's nothing to copy: git stops and says the cherry-pick is now empty. git cherry-pick --continue can't go on from there, because there's nothing to commit. git cherry-pick --abort gets you out. On your own computer, git cherry-pick --skip leaves that commit out instead.
When several commits stop partway
When you name several commits, git keeps a list of the ones still to copy. If it stops before the last one, the rest are waiting:
git cherry-pick --continuecommits the copy git stopped on, as above, then copies the rest. If another one stops, do the same again.git cherry-pick --abortgives up on the whole list. Your branch goes back to where it was before the cherry-pick, without the copies it had already made.
The other ways out of one commit don't end a list. git commit copies only the commit git stopped on, and the rest stay waiting until you run git cherry-pick --continue. git reset --hard puts your files back, but the cherry-pick stays in progress: git status still says Cherry-pick currently in progress., and git switch refuses to change branches.
If a commit in the list is already on your branch, git stops there with nothing to copy, and --continue can't get past it. Abort, then name the commits again without that one. So if a copy might already be on your branch, cherry-pick one commit at a time, oldest first.
Cherry-pick or merge?
Cherry-pick when you need one change now and not the rest of the branch. If you're going to merge the whole branch soon anyway, just merge it: copies of the same change on two branches make history harder to follow.
New commands
git cherry-pickgit cherry-pick --continuegit cherry-pick --abort
Explainer: Cherry-pick copies one commit
Graph as text
project: your repo, you are here
- HEAD → main at 35acbc3 "Add a contact page"
Branches and tags
- main at 35acbc3 "Add a contact page"
Commits, newest first
- 35acbc3 "Add a contact page"; parent a4b8d97; refs: HEAD → main
- a4b8d97 "Style the heading"; parent ab89288
- ab89288 "Add the home page"; parent 37d7cf7
- 37d7cf7 "Add a README"; no parent
Unreachable
- 6698940 "Try a huge heading"; parent 1c218b9
- 1c218b9 "Add a contact page"; parent d724c80
- d724c80 "Try an orange heading"; parent a4b8d97
Challenge 1 of 3
Story: The redesign timeline isn't ready, but one of its corrections is. Copy it into the main one.
The branch redesign isn't ready to merge. But one of its commits, Fix a typo on the about page, fixes a typo that main has too, and main needs the fix now.
You're on main. Copy just that one commit onto main. Leave redesign as it is.
Unlocks after Remotes & Collaboration and Undoing Things.
Terminal
Unlocks after Remotes & Collaboration and Undoing Things.
This Lesson can be played once Remotes & Collaboration and Undoing Things are complete. Its text and Explainer are open to everyone.