cherrybridge
v0.1.13
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
- Repo config: Per-repo defaults for
prefixandprojectUrlstored in.git/configand managed viacherrybridge config - 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.
label
Find all merged PRs whose title mentions any of a set of JIRA tickets (and that were merged into a given base branch) and apply a label to those PRs. Only closed-and-merged PRs are considered. Before applying, the command shows the extracted tickets and the list of PRs that will be labeled and prompts for confirmation. Duplicate ticket IDs are de-duplicated automatically.
Basic usage (positional):
cherrybridge label PROJECT-123 PROJECT-456 PROJECT-789
# commas are ignored, so this also works:
cherrybridge label PROJECT-123, PROJECT-456, PROJECT-789If --label is omitted, you'll be prompted for the label name with a default of cherry-YYYY-MM-DD (today's date).
Other input sources (combinable):
cherrybridge label --tickets "PROJECT-123, PROJECT-456" --label promote-to-staging
cherrybridge label --tickets-file tickets.txt --label promote-to-stagingOptions:
[tickets...]: Positional JIRA ticket IDs (e.g.PROJECT-123 PROJECT-456). Commas between tokens are tolerated.--tickets <text>: Inline text containing JIRA links/IDs (combined with any positional args).--tickets-file <path>: Path to a file containing JIRA links/IDs (combined with any other sources). At least one source of tickets is required.--label <label>: Label to apply to the found PRs. If omitted, you'll be prompted with defaultcherry-YYYY-MM-DD.--from <branch>: Branch the PRs were merged into. If omitted, you are prompted with defaultdevelopment.--prefix <prefix>: JIRA ticket prefix for extraction (optional; default fromcherrybridge configorPROJECT).--create: Create the label in the repository if it does not exist (usesgh label create --force). Omit to keep current behavior (label must already exist).
What happens:
- Tickets are extracted from the combined input (URLs and plain IDs like
PROJECT-123are supported) and de-duplicated. - Only PRs merged into the specified (or prompted) branch are considered; PRs are searched by title within that branch.
- You see a summary of tickets and PRs and are asked to confirm before any labels are applied.
config
Manage cherrybridge defaults stored in the repo's .git/config. Supported keys are prefix (JIRA ticket prefix) and projectUrl (base URL for ticket links in pr output).
Subcommands:
cherrybridge config set <key> <value> # set a value
cherrybridge config get <key> # print a value
cherrybridge config list # list all set values
cherrybridge config unset <key> # remove a valueExample:
cherrybridge config set prefix PROJECT
cherrybridge config set projectUrl https://company.atlassian.net/browseValues are stored under cherrybridge.<key> in .git/config and are local to the clone (not pushed to GitHub). See Repo config below for more.
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!Repo config
You can set default prefix and projectUrl per repo so you don't have to pass them every time. Values are stored in the repo's .git/config (local only — not pushed to GitHub) and managed via the config subcommand.
- Keys:
prefix(JIRA ticket prefix),projectUrl(base URL for ticket links in theprcommand body). - Precedence: Command-line flags override repo config; repo config overrides built-in defaults.
- Storage:
git config cherrybridge.<key>(i.e.,.git/config).
Set values:
cherrybridge config set prefix PROJECT
cherrybridge config set projectUrl https://company.atlassian.net/browseInspect:
cherrybridge config list
cherrybridge config get prefixRemove:
cherrybridge config unset projectUrlWorking 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]
