Two commands that shape Git history more directly than the ones in earlier lessons: git cherry-pick lifts a single commit from one branch and applies it to another, and git rebase replays a sequence of commits onto a different base. Both are powerful, both rewrite history, and both have a "do not use on shared branches" warning attached. This lesson covers the safe, useful applications you'll actually need as a QA engineer — and the lines you should not cross until you have more Git mileage.
git cherry-pick — grab one specific commit
The mental model: walk up to a tree, pick one fruit, take it back to your tree. Cherry-pick takes the changes from one commit and applies them as a new commit on your current branch.
The basic form:
git cherry-pick abc1234[main 7a92f1e] Fix flaky search test by waiting for network idle
Date: Tue May 5 14:22:08 2026 +0530
1 file changed, 3 insertions(+), 1 deletion(-)
Note the new commit hash (7a92f1e) is different from the original (abc1234). Cherry-pick doesn't move a commit — it copies its changes and creates a fresh commit with a new hash. The original stays put on its own branch.
When QA engineers reach for cherry-pick
- Wrong-branch fix. You wrote a flake fix on
maininstead of on your feature branch. Cherry-pick the commit onto the feature branch, thengit revert(or reset, if local) it on main. - Backporting one fix into a release branch. A bug fix lives on
main, but the team also maintainsrelease/v2.6for an old customer. Cherry-pick just the fix onto the release branch — you don't want to merge all ofmain. - Hotfixing without merging the rest of a branch. Your
feature/checkout-testshas 12 commits, only one of which is a flake fix everyone needs urgently. Cherry-pick that one ontomain; the other 11 stay on the branch until the feature is ready.
Cherry-picking multiple commits
git cherry-pick abc1234 def5678 fed4321Or a range (commits A through B inclusive, exclusive of A's predecessor):
git cherry-pick abc1234^..fed4321If a cherry-pick hits a conflict, Git pauses just like a merge:
error: could not apply abc1234... Fix flaky search test
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run "git cherry-pick --continue".
Resolve the file the way you would a merge conflict (Chapter 2, Lesson 3), then:
git add <resolved-file>
git cherry-pick --continueOr bail out:
git cherry-pick --abortgit rebase — replay your branch on top of another
Rebase answers a different question: "I've been working on a feature branch for two days, but main has moved on. How do I update my branch with the latest main, without a noisy merge commit?"
The rebase flow:
git switch feature/checkout-tests
git rebase mainFirst, rewinding head to replay your work on top of it...
Applying: Scaffold checkout test file
Applying: Add discount-code edge cases
Applying: Fix flaky timing on cart-update test
What happened internally:
- Git temporarily set your branch aside.
- It moved your branch's starting point to wherever
mainis now (the new "base"). - It replayed your commits one by one on top of that new base.
Each commit is re-created with a new hash — the original commits are gone, replaced by their rebased copies. Your branch now looks as if you'd started it from today's main, not yesterday's.
Rebase vs merge — same goal, different shape
Both bring the latest main into your feature branch. The difference is the resulting history:
- Merge (
git merge main) creates a merge commit combining both branches. History keeps a forked-and-rejoined shape. Honest but noisy. - Rebase (
git rebase main) replays your commits on top ofmain. History is linear — your commits look as if they happened after main's. Cleaner, but rewritten.
Pick rebase when your team prefers a clean, linear history (most modern teams do, especially with squash-and-merge PRs). Pick merge when you'd rather not rewrite local commits, or when the team's workflow doesn't care about linearity.
merge vs rebase at a glance
Bringing main into your feature branch — two shapes of history
git merge main
Creates a merge commit
Two parents — one from main, one from your branch
Original commits unchanged
Same hashes, same authors, same timestamps
Forked-and-rejoined history shape
Honest — shows that two lines existed in parallel
Safe on pushed branches
No history rewrite; teammates' clones stay consistent
Pick when in doubt
Especially if commits have already been pushed and reviewed
git rebase main
Replays your commits onto main
Each commit is re-created with a NEW hash
Linear history
As if your branch started from today's main, not yesterday's
No merge commit
Cleaner log, especially in squash-and-merge teams
Rewrites history — DON'T rebase pushed/shared commits
Force-push is needed; teammates' clones diverge
Pick when keeping history tidy matters
And only on your own unshared branch
The golden rule of rebasing
Borrowed verbatim from the Git docs and never wrong:
Do not rebase commits that exist outside your repository and that people may have based work on.
Translated: if you've pushed commits to a branch and a teammate has pulled them, do not rebase. Rebasing rewrites those commits' hashes; their copies on your teammate's machine no longer match yours; your next push is rejected, their next pull creates duplicates, everyone loses time.
Safe rebase scenarios:
- Your local feature branch, never pushed, you're polishing it before opening a PR.
- A branch only you push to, with team agreement that you can rebase as part of your workflow.
- After PR feedback, before merge, on a branch only you work on.
Unsafe scenarios:
- A long-running branch shared with multiple developers.
main,develop, or any release branch.- Anything you've pushed and someone else has pulled.
Interactive rebase — a quick taste
git rebase -i HEAD~3 opens an editor with your last 3 commits and lets you squash, reorder, edit, or drop each one. The most common QA use: tidying up a feature branch before opening a PR.
git rebase -i HEAD~3pick a8f2c91 WIP: scaffold search tests
pick 3a7b2c1 fix typo
pick 9b3d2f1 Add 5 search regression tests
Change pick to squash (or s) on commits 2 and 3 to fold them into commit 1:
pick a8f2c91 WIP: scaffold search tests
squash 3a7b2c1 fix typo
squash 9b3d2f1 Add 5 search regression tests
Save and close. Git asks you to write a unified commit message. Result: one clean commit, "Add 5 search regression tests," instead of three messy ones.
Don't go deep into interactive rebase yet. The takeaway: it exists, it's the tool when you want to clean up before a PR, and it falls under the same "local-only, never on shared branches" rule.
Day-to-day advice
For most QA engineers, the practical position is:
- Cherry-pick is the more useful of the two — keep it in your toolkit for the wrong-branch and backport scenarios.
- Rebase is powerful but easy to misuse. Until you're confident, use merge (
git merge mainfrom your feature branch) to bring main's changes in. The history is slightly less tidy; nothing is broken. - Once you've worked on a few teams and seen the workflows, you'll know when to introduce
rebase— and you'll do it on your own branch, before a PR.
A real QA scenario — cherry-picking a flake fix
You're three days into feature/payment-gateway-tests. Yesterday you committed a one-line fix to a flaky search test — it has nothing to do with the feature work, but you happened to be on that branch. Your team needs the search-test fix on main today. The branch isn't ready to merge.
Find the commit:
git log --oneline -109b3d2f1 Add tests for declined-card flow
3a7b2c1 Scaffold payment-gateway tests
7a92f1e Fix flaky search test by waiting for network idle ← the one you want
4c48901 Add cart fixture for discount-code edge cases
Switch to main, pull, cherry-pick:
git switch main
git pull
git cherry-pick 7a92f1e
git pushThe fix is now on main. Your feature branch is unchanged. CI's flake rate just dropped — and your feature work is still in flight.
⚠️ Common mistakes
- Rebasing a shared branch and force-pushing. The single most-cited cause of "we lost a day" stories on engineering teams. If others have pulled the branch, the rebase makes their commits orphans on their machines. Use
mergeinstead, or rebase only branches you alone work on. - Cherry-picking the same commit twice without realising. If you cherry-pick a commit, then later merge the source branch, the same change can appear as two different commits in your history. Git is usually smart enough to detect this and skip the duplicate, but not always — review with
git log --onelineafter cross-cutting operations. - Resolving rebase conflicts by aborting and re-trying. Beginners who hit a rebase conflict sometimes panic-
--abort, edit the source file, and try again. The conflict will keep happening because the underlying changes still overlap. Resolve in place: edit the file,git add,git rebase --continue. The friction is the rebase doing its job.
🎯 Practice task
Practice both commands in a safe sandbox. 25-30 minutes.
- In your
qa-sandboxrepo, make sure you're onmainwith at least 3 commits. Create a branch:git switch -c feature/sample. - On
feature/sample, make 3 commits — one per file, simple content. Confirm withgit log --oneline -5. - Cherry-pick: switch back to
main. Pick the middle commit's hash from your branch. Rungit cherry-pick <hash>. Confirm withgit log --oneline -5that the change is on main with a new hash. - Rebase: switch back to
feature/sample. Make a new commit onmain(git switch main && echo x > marker && git add marker && git commit -m "main moved"). Switch back to your branch and rungit rebase main. Read the output; confirm withgit log --oneline --graph --allthat your branch's commits now sit on top ofmain's new commit. - Interactive rebase: stay on
feature/sample. Rungit rebase -i HEAD~3. Change twopicks tosquash. Save. Write a combined commit message. Confirmgit log --onelineshows fewer commits. - Stretch: create a deliberate cherry-pick conflict (cherry-pick a commit that touches the same line as a commit on the destination branch). Resolve it: edit the file,
git add <file>,git cherry-pick --continue.
That closes Chapter 4. You can now save in-progress work, read history, undo mistakes safely, and shape history with cherry-pick and rebase. Chapter 5 turns the focus to test automation projects specifically — .gitignore, test data, and Git hooks that run your suite before code leaves your machine.