cherrybridge
v0.1.1
Published
Cherry-pick merged PR merge commits (by label) from one branch to another, resumable.
Readme
cherrybridge
Resumable cherry-picking of merged PR merge commits (selected by label) from one base branch to another.
Features
- Label-based PR selection: Automatically finds and cherry-picks PRs based on GitHub labels
- Resumable: Pause and resume cherry-picking sessions, even after resolving conflicts
- Automatic detection: Detects already-picked commits using Git's
-xflag - Smart defaults: Defaults to
development→stagingworkflow (customizable) - Branch config storage: Remembers your settings per branch for seamless continuation
- Conflict handling: Clear instructions when conflicts occur
Requirements
- git: Version control system
- GitHub CLI (
gh): Must be installed and authenticated (gh auth login)
Installation
Global Installation (Recommended)
npm install -g cherrybridgeLocal Installation
npm install cherrybridge
npx cherrybridge --versionVerify Installation
cherrybridge --versionYou should see the version number. If you get a "command not found" error, make sure npm's global bin directory is in your PATH.
Quick Start
The simplest workflow:
# Start cherry-picking PRs with a specific label
cherrybridge pick
# When prompted:
# 1. Enter the PR label (e.g., "feature:ABC-123")
# 2. Enter the promotion branch name (where cherry-picks will be applied)
# cherrybridge will:
# 1. Fetch all merged PRs with that label from development
# 2. Show you which PRs will be cherry-picked
# 3. Ask for confirmation
# 4. Cherry-pick them one by one onto the promotion branchThat's it! If there are no conflicts, you're done. If conflicts occur, see the Conflict Resolution section.
Commands
pick
Start a new cherry-picking session. This command:
- Fetches all merged PRs with the specified label from the source branch
- Filters out PRs that have already been cherry-picked
- Shows you a summary and asks for confirmation
- Cherry-picks each PR merge commit one by one
- Stops if a conflict occurs (you resolve it, then use
continue)
Basic usage:
cherrybridge pickWith flags:
cherrybridge pick --label feature:ABC-123 --from development --to staging --via promote/abc-123Options:
--from <branch>: Source base branch PRs were merged into (default:development)--to <branch>: Target base branch to promote into (default:staging)--label <label>: Label used to group PRs (e.g.,feature:ABC-123)--via <branch>: Branch to use for promotion (where cherry-pick commits will be applied). Defaults to current branch if it's not "development" or "staging"
What happens:
- If
--viabranch doesn't exist, it's created from the target branch - If
--viabranch exists, you're checked out to it - Config is stored on the branch for future
continuecommands - You'll see ASCII art and a confirmation prompt before cherry-picking starts
continue
Continue an in-progress cherry-pick or pick up newly-merged PRs. This command:
- Continues any in-progress cherry-pick (if you resolved conflicts)
- Re-fetches PRs from GitHub to catch any new merges
- Cherry-picks any newly-merged PRs that weren't there before
Basic usage:
cherrybridge continueWith flags:
cherrybridge continue --label feature:ABC-123 --from development --to staging --via promote/abc-123Smart behavior:
- If you're on a branch with stored config, it automatically uses those values
- If config is incomplete, it prompts for missing values
- Command-line flags always override config values
When to use:
- After resolving conflicts from a
pickcommand - When new PRs with the same label have been merged into the source branch
- To resume a cherry-picking session
status
Check which PRs are pending for cherry-picking. Shows:
- Total PRs found with the label
- How many are already picked
- List of pending PRs
Basic usage:
cherrybridge statusWith flags:
cherrybridge status --label feature:ABC-123 --from development --to staging --via promote/abc-123Output example:
Session: feature:ABC-123
From: development → To: staging
Promotion branch: promote/abc-123
PRs found: 5
Pending: 2
Pending PRs:
- #123: Add new feature (a1b2c3d4)
- #125: Fix bug (e5f6g7h8)cancel
Abort an in-progress cherry-pick and remove branch config. This runs git cherry-pick --abort to clean up the current cherry-pick operation and removes the stored config for the current branch.
Usage:
cherrybridge cancelWhat happens:
- Aborts the current cherry-pick operation (
git cherry-pick --abort) - Removes stored config for the current branch (label, fromBranch, toBranch)
- Provides a clean slate if you want to start over
Note: This doesn't delete branches or affect already-completed cherry-picks. If you want to keep the config and just abort the cherry-pick, use git cherry-pick --abort directly.
Advanced Usage
Using Command-Line Flags
For automation or to avoid prompts, you can specify all options via flags:
cherrybridge pick \
--label feature:ABC-123 \
--from development \
--to staging \
--via promote/abc-123This skips all prompts (except the confirmation before cherry-picking starts).
Note: If you're on "development" or "staging" branch, you'll be prompted for the promotion branch name since those branches cannot be used for promotion.
Branch Config Storage
cherrybridge automatically stores configuration per branch using Git's branch-specific config. This means:
- After running
pick, your settings are remembered - Running
continueon the same branch automatically uses stored config - No manual config files to manage
- Config is local only (not pushed to GitHub)
How it works:
- Config is stored when you run
pickorcontinue - Stored values:
label,fromBranch,toBranch - Accessed via:
git config branch.<branch-name>.cherrybridge.*
Example:
# First time - enter values
cherrybridge pick --label feature:ABC-123
# Config stored on promotion branch
# Later - automatically uses config
cherrybridge continue
# No prompts needed!Working with Multiple Promotion Branches
You can have multiple promotion branches for different labels:
# First promotion branch
cherrybridge pick --label feature:ABC-123 --via promote/abc-123
# Second promotion branch (different label)
cherrybridge pick --label bugfix:XYZ-456 --via promote/xyz-456Each branch maintains its own config, so continue knows which label to use.
Custom Source/Target Branches
By default, cherrybridge assumes development → staging, but you can use any branches:
cherrybridge pick \
--label release:v1.0.0 \
--from staging \
--to production \
--via promote/v1.0.0Conflict Resolution
When a conflict occurs during cherry-picking, cherrybridge stops immediately and shows clear instructions.
What Happens
- Cherry-pick stops at the conflicting commit
- You see a message indicating which PR caused the conflict
- Instructions are displayed for resolving it
Step-by-Step Resolution
1. Identify conflicted files:
git status2. Open conflicted files and resolve conflicts:
- Look for conflict markers:
<<<<<<<,=======,>>>>>>> - Edit files to resolve conflicts
- Remove conflict markers
- Save files
3. Stage resolved files:
# Stage specific files
git add path/to/file1 path/to/file2
# Or stage all resolved files
git add .4. Continue cherry-picking:
cherrybridge continuecherrybridge will:
- Continue the current cherry-pick
- Then check for any newly-merged PRs and cherry-pick those too
Aborting a Cherry-Pick
If you want to abort the entire cherry-pick operation:
cherrybridge cancelThis runs git cherry-pick --abort and cleans up the in-progress state.
Example Conflict Workflow
# Start cherry-picking
cherrybridge pick --label feature:ABC-123
# Conflict occurs on PR #123
# Output shows:
# ⚠️ Conflict encountered on PR #123 (a1b2c3d4).
#
# To resolve:
# 1. Fix the conflicts in the files (remove conflict markers)
# 2. Stage the resolved files: git add <file>
# 3. Continue: cherrybridge continue
# Fix conflicts in your editor
vim src/file.ts
# Stage resolved files
git add src/file.ts
# Continue
cherrybridge continue
# ✅ Continues cherry-picking remaining PRsTips and Best Practices
When to Use Flags vs Prompts
Use flags when:
- Automating in scripts
- You know all values upfront
- You want to avoid any prompts
Use prompts when:
- Running interactively
- You're not sure of exact values
- You want cherrybridge to remember settings (config storage)
Prompts you'll see:
- PR label: Always prompted if not provided via
--label - Promotion branch: Prompted if not provided via
--viaand current branch is "development" or "staging" (these cannot be used as promotion branches)
Branch Naming Conventions
While cherrybridge doesn't enforce naming, consider:
promote/<label-sanitized>: Clear and organizedpromote/<feature-name>: Descriptivestaging-pr/<ticket-number>: Team convention
The --via flag lets you use any branch name.
Working with Multiple Labels
If you have multiple labels to promote:
# Promote feature PRs
cherrybridge pick --label feature:ABC-123 --via promote/features
# Promote bugfix PRs (separate branch)
cherrybridge pick --label bugfix:XYZ-456 --via promote/bugfixesEach branch maintains separate config, so continue works independently.
Troubleshooting
"Command not found: cherrybridge"
- Make sure you installed globally:
npm install -g cherrybridge - Check your PATH includes npm's global bin directory
- Try using
npx cherrybridgeif installed locally
"GitHub CLI (gh) is required"
- Install GitHub CLI: https://cli.github.com/
- Authenticate:
gh auth login
"Working tree is not clean"
- Commit or stash your changes first
- Exception:
continueallows dirty working tree if you're resolving conflicts
"Not in a git repository"
- Run cherrybridge from within a git repository
- Make sure you're in the repo root or a subdirectory
Config not being used
- Make sure you're on the branch where config was stored
- Check config exists:
git config branch.<branch-name>.cherrybridge.label - Use
--viaflag to specify the branch explicitly
PRs not being detected
- Ensure PRs were merged (not closed) into the source branch
- Verify PRs have the correct label
- cherrybridge supports both "Create a merge commit" and "Squash and merge" strategies
- Rebase and merge may not work reliably (commits are replayed individually)
- Run
gh pr list --state merged --base development --label feature:ABC-123to verify
How It Works
Commit Detection
cherrybridge uses Git's -x flag when cherry-picking and automatically detects the commit type:
For merge commits:
git cherry-pick -m 1 -x <merge-commit-sha>For squash commits:
git cherry-pick -x <squash-commit-sha>The -x flag adds (cherry picked from commit <sha>) to the commit message. cherrybridge then searches commit messages to detect which PRs have already been cherry-picked, avoiding duplicates.
cherrybridge detects commit type using git rev-list --parents:
- 3 hashes = merge commit (uses
-m 1) - 2 hashes = regular commit/squash (no
-mflag)
PR Fetching
Every time you run pick or continue, cherrybridge:
- Runs
git fetch --all --pruneto update local refs - Uses
gh pr listto fetch merged PRs with the specified label - Uses the
mergeCommitfield (populated for both merge and squash merges) - Sorts PRs by merge time (oldest first)
Branch Config Storage
Config is stored using Git's branch-specific configuration:
git config branch.promote/abc-123.cherrybridge.label "feature:ABC-123"
git config branch.promote/abc-123.cherrybridge.fromBranch "development"
git config branch.promote/abc-123.cherrybridge.toBranch "staging"This is:
- Local only (not pushed to GitHub)
- Branch-specific (each branch has its own config)
- Automatic (no manual management needed)
Merge Strategy Support
cherrybridge supports multiple merge strategies:
Merge Commits (Create a merge commit):
- Uses
git cherry-pick -m 1 -xto select the first parent (PR side) - Works seamlessly with merge commits
Squash Merges (Squash and merge):
- Automatically detects squash commits (single-parent commits)
- Uses
git cherry-pick -xwithout the-mflag - GitHub provides the squash commit SHA in the
mergeCommitfield
Rebase and Merge:
- May not work reliably as commits are replayed individually
- No single commit SHA represents the entire PR
cherrybridge automatically detects the commit type and uses the appropriate cherry-pick command.
Development
For contributors or local development:
# Clone the repository
git clone <repo-url>
cd cherrybridge
# Install dependencies
npm install
# Build the project
npm run build
# Link for local testing
npm linkAfter linking, you can test your changes locally using cherrybridge commands.
Examples
Complete Workflow Example
# 1. Start cherry-picking
cherrybridge pick --label feature:ABC-123
# Enter branch name when prompted: promote/abc-123
# Confirm cherry-picking 3 PRs
# 2. Conflict occurs on PR #123
# Fix conflicts, then:
git add .
cherrybridge continue
# 3. Check status
cherrybridge status
# Shows: 2 PRs pending
# 4. Continue (picks remaining PRs)
cherrybridge continue
# ✅ Done! All PRs cherry-picked
# 5. Push and create PR
git push -u origin promote/abc-123
gh pr create --base staging --head promote/abc-123Using All Flags
cherrybridge pick \
--label release:v2.0.0 \
--from staging \
--to production \
--via promote/v2.0.0Checking Status Before Starting
# Check what would be cherry-picked
cherrybridge status --label feature:ABC-123
# Then start if you're happy with the list
cherrybridge pick --label feature:ABC-123Resuming After New PRs Merge
# Initial cherry-pick
cherrybridge pick --label feature:ABC-123
# Later, new PRs merge with same label
cherrybridge continue
# Automatically detects and cherry-picks new PRsLicense
[Add your license here]
Contributing
[Add contribution guidelines here]
