This error occurs when Git cannot find the commit you're trying to cherry-pick. The most common cause is that the commit exists on a remote branch that hasn't been fetched locally. Fetching from the remote usually resolves the issue.
When you run `git cherry-pick <commit-hash>`, Git attempts to locate that specific commit in your local repository's object database. The "fatal: bad revision" error means Git cannot find any object (commit, tag, or branch) matching the identifier you provided. Git stores commits locally, and your repository only knows about commits that have been fetched from remotes or created locally. If you're trying to cherry-pick a commit that exists in a teammate's branch or a remote repository, your local Git simply doesn't have that commit in its database yet. This error can also occur if the commit hash is mistyped, the commit was garbage collected after its branch was deleted, or you're using an incorrect syntax for specifying commit ranges. Understanding Git's distributed nature is key to resolving this issue - commits must exist locally before you can operate on them.
The most common fix is to fetch commits from the remote before cherry-picking. Your local repository may not know about commits that exist only on the remote server.
# Fetch all branches from all remotes
git fetch --all
# Then retry the cherry-pick
git cherry-pick abc1234If you only need commits from a specific remote:
# Fetch from origin only
git fetch origin
# Fetch a specific branch
git fetch origin feature-branchAfter fetching, Git will have the commit in its local object database, and the cherry-pick should succeed.
Before cherry-picking, confirm the commit actually exists and you have the correct hash.
# Check if the commit exists locally
git show abc1234
# If this also shows "bad revision", the commit isn't in your local repoIf the commit exists on a remote:
# View the commit on a remote branch (after fetching)
git log origin/main --oneline | grep abc1234
# Or search all branches
git branch -a --contains abc1234Get the full commit hash from a short hash:
# Expand short hash to full hash
git rev-parse abc1234If rev-parse fails, the commit definitely doesn't exist locally.
If the commit is on a specific branch, make sure that branch's data is up to date locally.
# If the commit is on 'feature-x' branch
git checkout feature-x
git pull origin feature-x
# Switch back to your branch
git checkout your-branch
# Now cherry-pick should work
git cherry-pick abc1234Alternative without switching branches:
# Fetch and update the remote tracking branch
git fetch origin feature-x:refs/remotes/origin/feature-x
# Cherry-pick the commit
git cherry-pick abc1234This ensures you have the latest commits from the branch where your target commit lives.
If the commit exists in a different repository (like a fork or upstream repo), you need to add it as a remote first.
# Add the other repository as a remote
git remote add upstream https://github.com/original-owner/repo.git
# Fetch commits from that remote
git fetch upstream
# Now you can cherry-pick the commit
git cherry-pick abc1234Example: Cherry-picking from a fork:
# Add colleague's fork
git remote add colleague https://github.com/colleague/repo.git
# Fetch their branches
git fetch colleague
# Cherry-pick their commit
git cherry-pick def5678Verify your remotes:
git remote -vIf you're cherry-picking a range of commits, ensure you're using the correct syntax.
Correct range syntax:
# Cherry-pick commits from A to B (exclusive of A)
git cherry-pick A..B
# Cherry-pick commits from A to B (inclusive of A)
git cherry-pick A^..BCommon mistakes:
# WRONG: Using hyphen instead of double-dot
git cherry-pick abc1234-def5678 # This won't work!
# CORRECT: Use double-dot for ranges
git cherry-pick abc1234..def5678Cherry-pick multiple specific commits:
# List commits separated by spaces
git cherry-pick abc1234 def5678 ghi9012The A..B syntax means "commits reachable from B but not from A", which is typically what you want for cherry-picking a series.
If your repository is a shallow clone, it may not contain the commit history you need.
Check if you have a shallow clone:
git rev-parse --is-shallow-repository
# Returns "true" if shallowUnshallow the repository:
# Fetch the complete history
git fetch --unshallow
# Then retry cherry-pick
git cherry-pick abc1234Fetch more history incrementally:
# Fetch 100 more commits
git fetch --deepen=100Shallow clones are common in CI/CD pipelines to speed up builds. If you need to cherry-pick in CI, either unshallow or adjust the clone depth:
# Clone with more history
git clone --depth=100 https://github.com/user/repo.gitIf the commit was on a deleted branch, it may have been garbage collected. You have limited options:
Check if the commit is still in reflog:
# Search reflogs for the commit
git reflog | grep abc1234
# Or search all reflogs
git reflog --all | grep abc1234If found in reflog, you can still access it:
git cherry-pick abc1234If not found locally, check the remote:
The commit might still exist on GitHub/GitLab even if the branch was deleted. You can:
1. Check the PR/MR where the commit was introduced
2. Ask the colleague who made the commit to push their branch again
3. Use the GitHub/GitLab API to access the commit if it exists in any refs
Prevent future garbage collection:
# Create a tag to preserve important commits
git tag preserve-abc1234 abc1234Once garbage collected, commits cannot be recovered locally. This typically happens 30+ days after a branch is deleted.
If cherry-pick continues to fail, you can apply the changes using other methods.
Create and apply a patch:
# On a machine that has the commit, create a patch
git format-patch -1 abc1234
# Transfer the .patch file, then apply it
git apply 0001-commit-message.patch
# Or apply and create a commit
git am 0001-commit-message.patchCopy changes manually using diff:
# Get the diff from GitHub/GitLab and apply locally
curl -L https://github.com/user/repo/commit/abc1234.patch | git applyFor GitHub/GitLab commits:
You can append .patch to any commit URL to download it:
- GitHub: https://github.com/user/repo/commit/abc1234.patch
- GitLab: https://gitlab.com/user/repo/-/commit/abc1234.patch
Then apply:
curl -L "https://github.com/user/repo/commit/abc1234.patch" | git am### Understanding Git's Distributed Model
Git is a distributed version control system where each clone is a complete repository. When you clone, you get a full copy of the history, but only for branches that existed at clone time. New commits pushed to the remote after your clone won't automatically appear in your local repository.
The command git pull is actually git fetch + git merge. If you only pull your current branch, you won't have commits from other branches. This is why git fetch --all is often necessary before cherry-picking from different branches.
### Why "Bad Revision" and Not "Commit Not Found"?
Git uses the term "revision" because the argument to cherry-pick can be:
- A commit hash (full or abbreviated)
- A branch name (resolves to the branch's HEAD commit)
- A tag name
- A relative reference like HEAD~3 or main^2
When Git says "bad revision", it means none of these lookups succeeded for the identifier you provided.
### Cherry-Pick vs Merge vs Rebase
Understanding when to use each:
| Method | Use Case | History Impact |
|--------|----------|----------------|
| cherry-pick | Copy specific commits to current branch | Creates new commits with new hashes |
| merge | Combine entire branch | Creates merge commit, preserves history |
| rebase | Replay commits on new base | Rewrites commit history |
Cherry-pick is ideal when you need only specific commits, not an entire branch. However, it creates new commits with different hashes, which can cause issues if you later merge the original branch.
### Avoiding Common Pitfalls
1. Always fetch before cherry-picking from remote branches - Make this a habit
2. Use full commit hashes when possible - Avoids ambiguity with short hashes
3. Don't cherry-pick merge commits without `-m` - Merge commits have multiple parents
4. Check for conflicts - Cherry-pick can have merge conflicts just like merge/rebase
# Cherry-picking a merge commit (specify parent)
git cherry-pick -m 1 abc1234### Git Fetch Variations
# Fetch everything from all remotes
git fetch --all
# Fetch with pruning (remove deleted remote branches)
git fetch --all --prune
# Fetch tags
git fetch --tags
# Fetch specific remote
git fetch origin
# Fetch and update a local branch reference
git fetch origin main:mainwarning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server