A CLI utility written in Go that allows you to cherry-pick entire GitHub pull requests to a destination branch. GitHub doesn't have this functionality ready-to-use, so this project solves that problem by automating the cherry-pick process while preserving the original PR's metadata.
- Go (for building the utility)
- GitHub CLI (
gh) - must be pre-configured and authenticated - Git repository with proper access permissions
go install github.com/theyoprst/gh-cp/cmd/gh-cp@latestThis will download, build, and install the gh-cp binary to your $(go env GOPATH)/bin directory.
# Clone the repository
git clone https://github.com/theyoprst/gh-cp.git
cd gh-cp
# Build and install
make install# Check if gh-cp is available
gh-cp --helpNote: Make sure your $(go env GOPATH)/bin is in your system's $PATH environment variable.
The standard go install github.com/theyoprst/gh-cp/cmd/gh-cp@latest command won't upgrade if you already have the same version installed. Use one of these methods to force an upgrade:
go install -a github.com/theyoprst/gh-cp/cmd/gh-cp@latestgo clean -cache && go install github.com/theyoprst/gh-cp/cmd/gh-cp@latestgo clean -modcache && go install github.com/theyoprst/gh-cp/cmd/gh-cp@latestNote: The -modcache option removes all cached Go modules and will cause slower builds for all Go projects until modules are re-downloaded.
For users managing many Go binaries, consider tools like gup which can update all Go binaries automatically:
# Install gup
go install github.com/nao1215/gup@latest
# Update all Go binaries
gup updategh-cp <pull-request-number> <target-branch> [--dry-run]Parameters:
pull-request-number- The number of the merged pull request to cherry-picktarget-branch- The destination branch to cherry-pick the changes to (can bebranchorremote/branchformat)--dry-run- (Optional) Preview mode: shows what would be done without making any remote changes--skip-merged-check- (Optional) Skip check that PR is merged (use with caution when cherry-picking unmerged PRs)
Examples:
# Cherry-pick PR #1319 to release/v2.1 branch
gh-cp 1319 release/v2.1
# Cherry-pick PR #1319 to origin/release/v2.1 branch
gh-cp 1319 origin/release/v2.1
# Preview the cherry-pick operation without making changes
gh-cp 1319 release/v2.1 --dry-run
# Cherry-pick an unmerged PR (use with caution)
gh-cp 1319 release/v2.1 --skip-merged-check-
Fetches PR Information: Uses
gh pr view 1319 --json "number,title,body,state,baseRefName,mergeCommit,commits,labels"to retrieve all information about the pull request -
Validates PR State: Ensures the PR is merged (cherry-picking unmerged changes is not supported)
-
Fetches Remote State: Automatically fetches the latest state of the target branch from the remote
-
Creates Isolated Worktree: Creates a temporary git worktree to perform operations without affecting your current working directory, allowing cherry-picking even with uncommitted changes
-
Creates New Branch: Creates a new branch with the naming pattern
cherry-pick-to/target-branch/from/original-branch. If the branch already exists, adds incremental suffixes (/0,/1, etc.) -
Cherry-picks Changes: Applies all commits from the original PR to the new branch in the isolated worktree
-
Creates New PR: Pushes changes and creates a new pull request targeting the specified branch with:
- Title prefixed with
[cherry-pick] - Body prefixed with a reference message linking to the original PR
- All original labels copied over
- Same description as the original PR
- Base branch set to the target branch you specified
- Title prefixed with
- Conflict Resolution: The tool does not automatically resolve merge conflicts. If conflicts occur during cherry-picking, the tool will leave the worktree in place and provide instructions for manual resolution
- Merged PRs Only: By default, only works with merged pull requests (use
--skip-merged-checkto override)
When cherry-pick conflicts occur, the tool will:
- Leave the temporary worktree in place (usually in
/tmp/gh-cp-worktree-*) - Display the worktree path and provide step-by-step manual resolution instructions
- Exit with an error message containing all necessary commands to complete the process
# Cherry-pick PR #1319 to the release/v2.1 branch
gh-cp 1319 release/v2.1This will:
- Fetch information about PR #1319
- Create a temporary worktree to isolate operations
- Create a unique branch name like
cherry-pick-to/release-v2.1/from/feature-branch-name/0(incrementing the suffix if needed) - Cherry-pick all commits from PR #1319 in the isolated worktree
- Push the new branch (with force to handle conflicts)
- Create a new PR from the cherry-pick branch →
release/v2.1titled[cherry-pick] Original PR Titlewith a link back to PR #1319 - Clean up the temporary worktree
Use --dry-run to preview operations without making any remote changes:
gh-cp 1319 release/v2.1 --dry-runIn dry-run mode, the tool will:
- ✅ Fetch PR information and validate it's merged
- ✅ Create temporary worktree and cherry-pick commits
- 🔍 Show push command that would be executed (from worktree)
- 🔍 Show PR creation command that would be executed
- ✅ Clean up temporary worktree (your working directory remains untouched)
# Build the binary
make build
# Clean build artifacts
make clean# Run linters
make lint
# Auto-fix linting issues where possible
make lint-fix# Run tests
make test# Build and install to $(go env GOPATH)/bin
make installcmd/gh-cp/- Main application entry pointinternal/github/- GitHub API integrationinternal/git/- Git operationsinternal/cherry/- Core cherry-pick logic