Cherry-pick PRs with ease! Automatically cherry-pick merged pull requests marked with a specific emoji in their title or with a specific label.
Why Cherri? It's a blend of "cherry-pick" and the French "chΓ©rie" (sweetheart), because let's face it - some commits are just more loveable than others. When you mark a PR with that little cherry emoji, you're essentially saying "this one's my chΓ©rie" - it's the commit equivalent of a love letter that deserves to be cherry-picked and brought along to every important branch.
Cherri is a CLI tool that automates the process of cherry-picking commits from merged pull requests. It searches for PRs with a specific emoji (default: π) in their title OR PRs with a specific label, and cherry-picks all commits from those PRs to your current branch.
Perfect for:
- Backporting features to release branches
- Maintaining LTS versions
- Selective feature deployment
- Managing hotfixes across multiple branches
Install Cherri globally using npm:
npm install -g cherri- Node.js (v16 or higher)
- Git installed and configured
- GitHub Personal Access Token with repo access
- You must be in the target git repository when running the command
-
Create a GitHub Personal Access Token:
- Go to GitHub Settings β Developer settings β Personal access tokens
- Generate a new token with
reposcope - Copy the token
-
Set the environment variable:
export GITHUB_TOKEN="your_github_token_here"
Or add it to your
.bashrc/.zshrc:echo 'export GITHUB_TOKEN="your_github_token_here"' >> ~/.bashrc
Before running Cherri, please set up your merge tool for automatic conflict resolution. When conflicts occur during cherry-picking, they will be handled one by one, opening your configured editor for each conflicted file individually.
Add one of these configurations to your global ~/.gitconfig file:
For Cursor:
[merge]
tool = cursor
[mergetool "cursor"]
cmd = cursor --reuse-window --wait $MERGEDFor VS Code:
[merge]
tool = vscode
[mergetool "vscode"]
cmd = code --wait $MERGEDFor other popular editors:
# For Vim πΏ
[merge]
tool = vimdiff
# For Emacs π€ ( only tsoding πΏ uses this lol )
[merge]
tool = emergeAfter adding this configuration, git will automatically open your editor when conflicts need to be resolved during cherry-picking.
Instead of specifying repository details via command-line flags each time, you can create a cherri.json configuration file in your project root to define reusable profiles.
Create a cherri.json file in your project root:
{
"profiles": [
{
"name": "main",
"configuration": {
"owner": "your-org",
"repo": "your-repo",
"emoji": "π",
"label": "cherry-pick",
"prTitle": "Custom Release PR Title",
"prBodyTemplate": "## π Release Backport\n\nBackporting {{prCount}} PRs to {{targetBranch}}:\n\n{{prList}}\n\n### Stats\n- Commits: {{commitCount}}\n- Date: {{date}}"
}
},
{
"name": "staging",
"configuration": {
"owner": "your-org",
"repo": "your-repo",
"emoji": "π",
"label": "hotfix"
}
}
]
}Use the -p or --profile flag to specify which profile to use:
# Use the "main" profile configuration
cherri -p main
# Use the "staging" profile configuration
cherri -p staging
# You can still override specific options when using a profile
cherri -p main --interactive --since 2Each profile's configuration object supports:
| Field | Description | Required | Default |
|---|---|---|---|
owner |
GitHub repository owner | Yes | - |
repo |
GitHub repository name | Yes | - |
emoji |
Emoji to search for in PR titles | No | π |
label |
Search for PRs with this label | No | - |
prTitle |
Custom title for the created PR (only used with --create-pr) |
No | Cherri: X PR(s) (Y selected) |
prBodyTemplate |
Custom template for PR body with variable substitution (only used with --create-pr) |
No | Default format |
Notes:
- When using
-p, you cannot specify--owneror--repoflags (they come from the profile) - Other command-line options can still be used and will override profile settings
- The configuration file is searched in the current directory and parent directories up to the git root
cherri -o <owner> -r <repo>cherri -p <profile-name>| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--profile |
-p |
Profile name from cherri.json configuration file | No | - |
--owner |
-o |
GitHub repository owner | Yes* | - |
--repo |
-r |
GitHub repository name | Yes* | - |
--since |
-s |
Time period to look back for PRs (e.g., '1w3d4h', '7d', '2' for 2 months) | No | 1 |
--since-branch |
- | Use branch creation date as cutoff (e.g., 'main', 'release/v1.0') - alternative to --since | No | - |
--emoji |
-e |
Custom emoji to search for in PR titles and display in logo | No | π |
--interactive |
-i |
Enable interactive mode for PR selection | No | false |
--select-commits |
- | Interactively select individual commits from each PR (requires -i) |
No | false |
--source-branch |
-b |
Source branch, defaults to the default branch | No | Auto-detected |
--label |
-l |
Search for PRs with this exact label (replaces title search) | No | - |
--fail-on-conflict |
- | Exit with error when conflicts are detected instead of prompting for resolution | No | false |
--create-pr |
- | Create a PR instead of direct cherry-picking. Optionally specify target branch (defaults to source branch) | No | false |
* Required unless using --profile with a configuration file
Note: Use either --since OR --since-branch, not both. They serve the same purpose but use different methods to determine the cutoff date for PRs.
cherri -o facebook -r reactcherri -o microsoft -r vscode -s 3cherri -o microsoft -r vscode -s 1w2dcherri -o microsoft -r vscode -s 7dcherri -o microsoft -r vscode -s 2h# Use either --since OR --since-branch, not both
cherri -o your-org -r your-repo --since-branch maincherri -o your-org -r your-repo --since-branch release/v2.0cherri -o your-org -r your-repo -e "π"cherri -o microsoft -r vscode -icherri -o your-org -r your-repo -i --select-commitscherri -o your-org -r your-repo -b release/1.0cherri -o your-org -r your-repo -l "cherry-pick"cherri -o your-org -r your-repo --fail-on-conflictcherri -o your-org -r your-repo --create-prcherri -o your-org -r your-repo --create-pr release/v1.0cherri -o your-org -r your-repo -s 1w --create-prcherri -o facebook -r react -s 2 -i -b main -l "hotfix" --fail-on-conflictThe --since flag supports flexible time period specifications. Alternatively, you can use --since-branch to use a branch's creation date as the cutoff.
w= weeksd= daysh= hoursm= minutes
# Complex combinations
cherri -s 1w3d4h # 1 week, 3 days, 4 hours ago
cherri -s 2d12h # 2 days, 12 hours ago
cherri -s 30m # 30 minutes ago
# Individual units
cherri -s 7d # 7 days ago
cherri -s 2h # 2 hours ago
cherri -s 45m # 45 minutes ago
# Backward compatible (bare numbers = months)
cherri -s 2 # 2 months ago (same as before)
cherri -s 1 # 1 month ago (default)
# Alternative: Branch-based cutoff
cherri --since-branch main # Since main branch was created
cherri --since-branch release/v1.0 # Since release branch was created- Backward Compatible: Bare numbers without units still work as months
- Flexible: Mix and match any combination of time units
- Precise: Calculations use milliseconds for accuracy
- Alternative: Use
--since-branchfor branch-based cutoffs instead of time calculations
When using the --create-pr flag, Cherri will create a pull request instead of directly cherry-picking commits. This is useful for review workflows where changes need approval before merging.
- Branch Creation: Creates a new branch with format
cherri/auto-{timestamp} - Cherry-picking: Applies all selected commits to the new branch
- PR Creation: Creates a pull request from the new branch to your target branch
- Cleanup: Switches back to your original branch
# Create PR for review instead of direct cherry-picking
cherri -o your-org -r your-repo --create-pr
# Output:
# Creating branch: cherri/auto-2025-09-11T12-30-45
# Pushing branch: cherri/auto-2025-09-11T12-30-45
# Creating pull request...
# β
PR Created Successfully!
# PR: https://github.com/your-org/your-repo/pull/123
# Branch: cherri/auto-2025-09-11T12-30-45
# Target: main- Title:
π Cherry-pick: X PR(s)(where X is the number of PRs) - Body: Contains summary of cherry-picked PRs, commit counts, and generation info
- Labels: Automatically tagged as cherry-pick related
This mode is perfect for:
- Code Review Requirements: When your workflow requires PR reviews
- Staging Environments: Creating intermediate PRs for testing
- Audit Trails: Maintaining a record of all cherry-pick operations
Customize the PR description using template variables in your cherri.json configuration. Variables are replaced at runtime when creating PRs with --create-pr.
{{prCount}}- Number of PRs successfully cherry-picked{{prList}}- Formatted list of PRs:- #123: Title (@author){{prListPlain}}- Simple comma-separated list:#123, #456, #789{{totalSelected}}- Total number of PRs originally selected{{emoji}}- The emoji used for marking PRs
{{commitCount}}- Number of commits successfully cherry-picked{{commitSkipped}}- Number of commits skipped
{{targetBranch}}- Target branch for the PR{{sourceBranch}}- Source branch where commits came from
{{date}}- Current date in ISO format (YYYY-MM-DD){{dateTime}}- Current date and time in ISO format{{timestamp}}- Unix timestamp in milliseconds
{{owner}}- Repository owner{{repo}}- Repository name
{
"prBodyTemplate": "Backporting {{prCount}} PRs to {{targetBranch}}\n\n{{prList}}"
}{
"prBodyTemplate": "## {{emoji}} Cherry-pick Summary\n\nThis PR backports **{{prCount}}** pull requests to `{{targetBranch}}`:\n\n{{prList}}\n\n### Statistics\n- **Total PRs Selected**: {{totalSelected}}\n- **PRs Cherry-picked**: {{prCount}}\n- **Commits Applied**: {{commitCount}}\n- **Commits Skipped**: {{commitSkipped}}\n\n### Branch Info\n- **Source**: {{sourceBranch}}\n- **Target**: {{targetBranch}}\n\n---\nGenerated by Cherri on {{date}}"
}{
"prBodyTemplate": "## Release Backport\n\nBackporting changes from {{sourceBranch}} to {{targetBranch}}:\n\n{{prList}}\n\n### Review Checklist\n- [ ] Code reviewed\n- [ ] Tests passing\n- [ ] Documentation updated\n- [ ] QA approved\n\n**Stats**: {{commitCount}} commits from {{prCount}} PRs\n\nCC: @release-team"
}{
"prBodyTemplate": "Cherry-picking PRs: {{prListPlain}}\n\nTotal commits: {{commitCount}}"
}Add prBodyTemplate to your profile configuration:
{
"profiles": [
{
"name": "production",
"configuration": {
"owner": "your-org",
"repo": "your-repo",
"emoji": "π",
"prTitle": "Production Backport",
"prBodyTemplate": "## Production Release\n\nBackporting {{prCount}} PRs:\n\n{{prList}}\n\n**Date**: {{date}}\n**Target**: {{targetBranch}}"
}
}
]
}Then use with --create-pr:
cherri -p production --create-prNotes:
- If no
prBodyTemplateis specified, Cherri uses the default format - Unrecognized variables remain as-is (e.g.,
{{unknownVar}}stays unchanged) - Use
\nfor line breaks in JSON strings - Templates work only with
--create-prmode
Cherri uses one of two search methods (not both simultaneously):
- Title Search (default): Looks for the emoji in PR titles
- Label Search: When using
--label, searches only by the exact label (ignores titles)
Search behavior:
# Title search - finds PRs with π in title
cherri -o org -r repo
# Label search - finds PRs with "cherry-pick" label (ignores titles completely)
cherri -o org -r repo -l "cherry-pick"Cherri automatically detects your repository's default branch (main/master) using git remote show origin. You can override this with the --source-branch option if needed.
-
Search Phase:
- Without
--label: Searches for merged PRs with the specified emoji in the title - With
--label: Searches for merged PRs with the specified label (ignores titles) - Time-based cutoff: Parses the
--sincetime period (supports complex formats like '1w3d4h', '7d', or '2' for months) - Branch-based cutoff: When using
--since-branch, uses the creation date of the specified branch as the cutoff date - Note: Use either
--sinceOR--since-branch, not both - they serve the same purpose - Filters PRs merged within the specified timeframe
- Without
-
Selection Phase:
- Interactive mode (
-i): Opens checkbox interface to select specific PRs - Non-interactive mode (default): Processes all found PRs automatically
- Interactive mode (
-
Processing Phase:
- Direct Mode (default): Cherry-picks commits directly to the target branch
- PR Mode (
--create-pr): Creates a new branch, cherry-picks commits, and creates a PR for review - Retrieves all commits from each selected PR
- Shows a summary of PRs and total commits to be processed
-
Cherry-pick Phase:
- For each commit:
- Checks if it already exists (by commit message)
- Attempts to cherry-pick
- If the commit SHA doesn't exist (rebased/squashed PRs), automatically finds the equivalent commit by message
- Handles conflicts by automatically opening your configured merge tool
- For each commit:
-
Conflict Resolution: Default behavior: When conflicts occur, your configured merge tool will automatically open one conflict at a time. Each conflicted file will be processed individually, allowing you to focus on resolving one conflict before moving to the next. If no merge tool is configured, you'll see:
π Please resolve conflicts in your editor 1. Fix the conflicted files 2. Save the files 3. Stage changes: git add . Then press: y - to continue after fixing conflicts s - to skip this commit q - to quit the processWith
--fail-on-conflict: The process will immediately exit with an error when any conflict is detected, without prompting for resolution. This is useful for automated environments like CI/CD where you want the process to fail fast on conflicts.
When you use the -i or --interactive flag, you'll see a checkbox interface:
π Found 12 PRs with π. Select specific PRs? Yes
? Select PRs to cherry-pick:
β―β― #1234 Fix authentication bug (john) β’ 12/1/2024
β #1235 Add new feature (sarah) β’ 12/2/2024
β― #1236 Update dependencies (bot) β’ 12/3/2024
Selected 1 PRs:
#1235 Add new feature
Controls:
- Use SPACE to select/deselect PRs
- Use ENTER to confirm selection
- Use arrow keys to navigate
When you use the --select-commits flag (requires -i), you can select specific commits from each PR:
cherri -o your-org -r your-repo -i --select-commitsWorkflow:
- First, select which PRs to cherry-pick (standard interactive mode)
- Then, for each selected PR, choose which commits to include:
[PR 1/3] #123: Fix authentication (5 commits)
? Select commits to cherry-pick:
β―β a1b2c3d feat: Add login validation
β d4e5f6g fix: Handle edge case
β― g7h8i9j test: Add unit tests (John Doe)
β k1l2m3n docs: Update README
β― o4p5q6r refactor: Clean up code
β Selected 3/5 commits from PR #123
Use Cases:
- Cherry-pick only bug fixes, skipping tests or documentation
- Exclude specific commits that might cause conflicts
- Fine-grained control over what gets backported
- Skip commits that are already present in target branch
Choose one of these two methods to mark PRs for cherry-picking:
Method 1: Via Title (default behavior) Add the emoji to PR titles:
π Fix: Critical bug in authentication flow
feat: Add new dashboard widget π
[π] Update dependencies for security patch
Method 2: Via Labels (use --label flag)
- Create a label in your repository (e.g., "cherry-pick", "backport", "hotfix")
- Apply the label to PRs you want to cherry-pick
- Use the
--labelflag to search for that specific label (this will ignore titles)
# Search for PRs with "cherry-pick" label (ignores titles)
cherri -o your-org -r your-repo -l "cherry-pick"β
Smart PR selection - Choose to select specific PRs or process all automatically
β
Interactive checkbox interface - Easy selection with visual feedback
β
Granular commit selection - Pick individual commits from each PR for fine-grained control
β
Flexible search methods - Search by emoji in titles OR by exact labels
β
Branch-based timeframes - Use branch creation dates instead of calculating time periods
β
PR creation mode - Create pull requests instead of direct cherry-picking for review workflows
β
Automatic conflict resolution - Automatically opens your configured merge tool for conflicts
β
One-by-one conflict handling - Processes conflicts individually for focused resolution
β
Automatic commit resolution - Handles rebased and squashed commits by finding matching messages
β
Interactive conflict resolution - Guides you through fixing conflicts when merge tool isn't configured
β
Fail-fast on conflicts - Option to exit immediately on conflicts for automated environments
β
Duplicate detection - Skips commits that are already in the target branch
β
Progress tracking - Shows real-time progress with spinners and status updates
β
Safe operation - Validates repository and branch before making changes
β
Auto version checking - Notifies when updates are available
β
Graceful interruption handling - Clean recovery from Ctrl+C or user cancellation \
main or release
Set your GitHub token:
export GITHUB_TOKEN="ghp_yourtoken"If you interrupt the process (Ctrl+C), check your git status:
git status
# If needed, abort any in-progress cherry-pick:
git cherry-pick --abort- Title search: Check that PRs contain the emoji in their titles
- Label search: Verify PRs have the exact label you're searching for
- Time/Branch filters: Verify the
--sincetimeframe or--since-branchbranch covers when PRs were merged - Note: Remember to use either
--sinceOR--since-branch, not both - Ensure PRs are actually merged (not just closed)
merge-toolnot configured: Rungit config merge.tool <tool>to set your preferred merge tool- Merge tool fails: The tool will fall back to manual conflict resolution, but all changes you made while using the merge-tool will be reverted.
π§ In Development:
- Dry run mode - Test cherry-picks without making changes, detect conflicts early
This project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request. Just remember to mark it with π if you want it cherry-picked!
Made with β€οΈ and π