Back to Blog
git

How to Merge Only Specific Changes from a Git Branch: Avoiding Unwanted Commits

Medianeth Team
July 29, 2025
8 minutes read

How to Merge Only Specific Changes from a Git Branch: Avoiding Unwanted Commits

Every developer has faced this nightmare scenario: you create a feature branch from develop to fix a critical bug, but when it's time to deploy, you realize you only need the actual fix—not the dozens of experimental changes from develop. This post shows you exactly how to surgically extract only the commits you need using Git cherry-pick, with real-world commands and troubleshooting tips.

The Problem: Contaminated Feature Branches

Here's a scenario that happened to our team last week:

The Setup:

  • Our develop branch had 15+ experimental features being tested
  • A critical bug was discovered in production requiring immediate attention
  • Developer Sarah created fix-1 from develop to address the bug
  • After fixing the bug, she realized fix-1 now contained:
    • ✅ The actual bug fix (2 commits)
    • ❌ All 15+ experimental features from develop
    • ❌ Database schema changes not ready for production

The Challenge: How to merge only the bug fix commits into master without bringing along all the experimental work?

Why Direct Merge Won't Work

Let's examine what would happen with a standard merge:

# This would bring ALL changes from develop $ git checkout master $ git merge fix-1 # Result: 50+ commits including experimental features # Production would get unstable code

The issue is that fix-1 contains the entire history of develop plus the fix commits. A direct merge would drag along everything, potentially breaking production.

Solution 1: Git Cherry-Pick (Recommended)

Git cherry-pick allows you to apply specific commits from one branch to another, creating new commits with the same changes but different commit hashes.

Step 1: Identify Your Target Commits

First, let's find the specific commits we want to cherry-pick:

# Check the commit history on fix-1 $ git log fix-1 --oneline --graph * 8f3a2b1 (fix-1) Fix: Handle null values in user preferences * 9c4e7d2 Fix: Add validation for email format * a1b2c3d (develop) Experimental: New dashboard layout * d4e5f6g Experimental: Database schema changes * ... (many more develop commits)

In our case, we only want the last two commits: 8f3a2b1 and 9c4e7d2.

Step 2: Cherry-Pick the Specific Commits

# Switch to master branch $ git checkout master # Cherry-pick the fix commits in order $ git cherry-pick 9c4e7d2 $ git cherry-pick 8f3a2b1 # Output: # [master 7a8b9c2] Fix: Add validation for email format # Date: Wed Jul 23 14:30:00 2025 -0400 # 2 files changed, 45 insertions(+), 3 deletions(-) # [master 3d4e5f6] Fix: Handle null values in user preferences # Date: Wed Jul 23 14:35:00 2025 -0400 # 1 file changed, 12 insertions(+), 2 deletions(-)

Step 3: Verify the Changes

# Check that only our fix commits are applied $ git log --oneline -5 3d4e5f6 Fix: Handle null values in user preferences 7a8b9c2 Fix: Add validation for email format abc1234 (origin/master, master) Previous stable commit # Verify no experimental changes came along $ git diff origin/master # Should only show changes related to the bug fix

Solution 2: The Diff/Patch Method (Alternative)

For situations where you need to extract changes that span multiple commits or when cherry-picking would create conflicts, the diff/patch approach works well:

Step 1: Create a Diff File

# Create a diff of only the files you changed $ git diff develop..fix-1 --name-only # This shows all files changed in fix-1 # Create a patch for specific files $ git diff develop..fix-1 -- src/utils/validation.js src/models/user.js > bug-fix.patch

Step 2: Apply the Patch

# Switch to master and apply the patch $ git checkout master $ git apply bug-fix.patch # Or use git apply with --check first to test $ git apply --check bug-fix.patch # Dry run $ git apply bug-fix.patch # Actually apply

Solution 3: Clean Branch Method (Nuclear Option)

When you have many commits and want to start fresh:

Step 1: Create a Clean Branch

# Create a new branch from master $ git checkout master $ git checkout -b hotfix-critical-bug

Step 2: Extract Changes Programmatically

# Method 1: Copy specific files $ git checkout fix-1 -- src/utils/validation.js src/models/user.js # Method 2: Use git archive for complex directory structures $ git archive fix-1 src/utils/ | tar -x -C /tmp/changes/ $ cp -r /tmp/changes/src/utils/* src/utils/

Step 3: Commit as Single Change

$ git add . $ git commit -m "Hotfix: Critical email validation bug"

Real-World Example: Complete Workflow

Let's walk through a complete example with actual commands and expected outputs:

The Setup

# Initial state $ git branch -a develop fix-1 * master remotes/origin/HEAD -> origin/master remotes/origin/develop remotes/origin/master # Check what changed in fix-1 $ git log --oneline master..fix-1 a8f3c2d (fix-1) Fix: Prevent email injection attacks b4e7d9a Fix: Add rate limiting to login endpoint c2d8f1e Experimental: Machine learning user recommendations ... (15 more commits)

The Cherry-Pick Process

# 1. Switch to master $ git checkout master Switched to branch 'master' Your branch is up to date with 'origin/master'. # 2. Cherry-pick security fixes only $ git cherry-pick b4e7d9a [master 9f8e7d2] Fix: Add rate limiting to login endpoint Author: Sarah Chen <sarah@medianeth.agency> Date: Wed Jul 23 14:15:00 2025 -0400 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/middleware/rate-limit.js $ git cherry-pick a8f3c2d [master 7d3e9f1] Fix: Prevent email injection attacks Author: Sarah Chen <sarah@medianeth.agency> Date: Wed Jul 23 14:20:00 2025 -0400 2 files changed, 34 insertions(+), 8 deletions(-) # 3. Verify the result $ git log --oneline -3 7d3e9f1 Fix: Prevent email injection attacks 9f8e7d2 Fix: Add rate limiting to login endpoint abc1234 Previous stable commit # 4. Test the changes $ npm test ✓ Security tests pass ✓ Rate limiting works correctly ✓ No experimental features detected

Best Practices and When to Use Each Method

Use Cherry-Pick When:

  • You have 2-10 specific commits to migrate
  • The commits are atomic and self-contained
  • You want to preserve commit history and authorship
  • Changes are relatively recent

Use Diff/Patch When:

  • Changes are spread across many commits
  • You need to exclude certain parts of commits
  • The target branch has diverged significantly
  • You want to review changes before applying

Use Clean Branch When:

  • You need to make additional changes during merge
  • The original branch history is too complex
  • You want to squash multiple commits into one
  • You're dealing with a critical production fix

Troubleshooting Common Issues

Issue 1: Cherry-Pick Conflicts

# Error: cherry-pick resulted in conflicts $ git cherry-pick a8f3c2d error: could not apply a8f3c2d... Fix: Prevent email injection attacks hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' # Solution: Resolve conflicts and continue $ git status # See conflicted files $ # Edit files to resolve conflicts $ git add . # Mark conflicts as resolved $ git cherry-pick --continue

Issue 2: Wrong Commit Range

# If you cherry-picked the wrong commit $ git log --oneline -2 wrong-commit-hash Fix: Wrong change applied another-wrong-hash Fix: Another incorrect change # Undo the last cherry-pick $ git reset --hard HEAD~2 # Cherry-pick the correct ones $ git cherry-pick correct-commit-hash

Issue 3: Missing Dependencies

# Error: changes depend on other commits $ git cherry-pick b4e7d9a error: could not apply b4e7d9a... Fix: Add rate limiting error: src/middleware/rate-limit.js: does not exist in index # Solution: Include dependent commits or create missing files $ git cherry-pick previous-commit-that-creates-file $ git cherry-pick b4e7d9a

Issue 4: Authentication Issues

# If commits have different authors and you need to preserve attribution $ git cherry-pick --allow-empty-message b4e7d9a $ git commit --amend --author="Sarah Chen <sarah@medianeth.agency>"

Advanced Techniques

Cherry-Pick Multiple Commits at Once

# Cherry-pick a range of commits $ git cherry-pick oldest-commit^..newest-commit # Cherry-pick specific commits $ git cherry-pick commit1 commit2 commit3 # Cherry-pick with custom message $ git cherry-pick -e commit-hash # Opens editor for commit message

Interactive Cherry-Pick with Rebase

# Interactive rebase to reorder/edit commits before cherry-picking $ git rebase -i develop fix-1 # Then cherry-pick from the cleaned branch

Production Deployment Checklist

Before deploying your cherry-picked changes:

  1. Verify Changes Only

    $ git diff origin/master | grep -v "^\+\+\+" | grep "^\+" | wc -l # Should show reasonable number of changed lines
  2. Run Complete Test Suite

    $ npm test $ npm run test:integration $ npm run security-scan
  3. Check for Configuration Changes

    $ git diff origin/master --name-only | grep -E '\.(json|yml|yaml|env)$'
  4. Review Database Migrations

    $ git diff origin/master -- 'migrations/*'

Key Takeaways

  • Cherry-pick is your surgical tool for extracting specific commits
  • Always verify what you're bringing with git diff before merging
  • Test thoroughly after cherry-picking to ensure no hidden dependencies
  • Document your process for future team members
  • Consider branch strategy to prevent this issue in future sprints

This post was written by Jomar, Senior Developer at Medianeth. We've helped dozens of development teams streamline their Git workflows and avoid production disasters. Want to work with us? Get in touch.

Let's Build Something Great Together!

Ready to make your online presence shine? I'd love to chat about your project and how we can bring your ideas to life.

Free Consultation 💬