Skill v1.0.0
currentTrusted Publisher100/100version: "1.0.0" name: cherry-pick-to-release description: 'Cherry-pick a merged main-branch PR onto a MsQuic release branch (release/X.Y).'
Cherry-Pick to MsQuic Release Branch
You are helping a maintainer back-port a fix from main to one or more MsQuic release branches (release/2.4, release/2.5, etc.).
This skill encodes the patterns the project uses.
When This Skill Activates
The user asks to cherry-pick / back-port / "CP" a PR or commit from main onto a release branch. Typical requests:
- "Cherry-pick #5942 to release/2.4 and release/2.5"
- "Back-port the ACK underflow fix to 2.5"
- "CP this commit to the 2.4 release branch"
Inputs You Need
Before doing anything, make sure you know:
- Source: a PR number on
main(preferred) or a commit SHA onorigin/main. - Target release branch(es): e.g.
release/2.4,release/2.5. If the
user is ambiguous (e.g. "to the release branches"), ask whether they want one branch or both, and which.
- Whether to push / open a PR. You must never push a branch or open a PR
without explicit permission. Stop and ask before any git push or gh pr create.
If anything is missing, ask before proceeding.
Project Conventions (must follow)
PR Title
[CP] <Original PR title> (#<original_pr_number>)
Examples actually used on the release branches:
[CP] Fix underflow in ACK frame parsing #5942(→ PR #5943 on 2.5, #5944 on 2.4)[CP] Fix SAL annotation placement on function templates (#5895)[CP] Free AES 256 GCM algorithm handle on cleanup (#5526)[CP] Fix double deref in connection pool error path (#5597)
When the same fix targets multiple release branches, the title is identical across PRs; only the target branch differs. After squash-merge, GitHub appends the new PR number, producing commits like [CP] Fix underflow in ACK frame parsing #5942 (#5943) on the release branch — this is expected and required (it makes traceability trivial).
Do not invent new prefixes; stick to [CP] unless asked.
PR Body
Use the exact body of the original PR, verbatim, including the ## Description, ## Testing, and ## Documentation sections as the original author wrote them. Do not rewrite, summarize, or augment them with cherry-pick commentary.
No additions or modification of the original description is acceptable.
Branch Naming
Project convention (observed on most recent cherry-pick PRs):
<user>/cp_<short_description>_<target_version>_copilot
The <short_description> is a snake_case summary of the fix, mirroring prior branches like cp_conn_pool_deref, cp_free_aes_256_gcm_handle, underflow_fix_cp.
Use one branch per target release branch (do not try to land both release branches from a single branch / PR).
Commits Inside the PR
- Almost always one commit — the cherry-picked commit, with its
original message preserved.
- Occasionally a second commit is acceptable if needed to make the
release branch build/pass tests (merge conflict resolutions and build fixes). Keep these tightly scoped to enabling the cherry-pick; do not sneak in unrelated changes.
- Squash-merge erases the multi-commit structure on the release branch.
- Do not add
(cherry picked from commit X)trailers — the project
doesn't use git cherry-pick -x; traceability comes from the PR title containing the original PR number.
Workflow
Follow these steps in order. Do not skip a phase.
Phase 1 — Identify the source commit on main
- If given a PR number, find its squash-merge commit on
origin/main:
``powershell gh pr view <orig_pr> --repo microsoft/msquic --json mergeCommit,state,title,body,baseRefName ` Verify state == MERGED and baseRefName == main`. If not merged, stop and tell the user — never cherry-pick an unmerged change.
- If given a SHA, confirm it is reachable from
origin/main:
``powershell git --no-pager log -1 --format="%H %s" <sha> git --no-pager branch -r --contains <sha> | Select-String "origin/main" ``
- Capture the original PR title and body — you'll reuse them.
Phase 2 — Prepare the local branch
Repeat for each target release branch.
- Make sure the working tree is clean (
git status). If not, stop and ask. - Fetch latest refs:
git fetch origin --prune. - Create the branch from the tip of the release branch:
``powershell git checkout -b <user>/cp_<short_desc>_2_5_copilot origin/release/2.5 ``
Phase 3 — Apply the cherry-pick
- Run
git cherry-pick <commit_sha>(no-x). - On conflicts:
- Resolve them, keeping the spirit of the original fix.
- If the conflict is non-trivial, briefly summarize the resolution in the PR body under
## Descriptionso reviewers know what differs frommain. - If the fix depends on code that doesn't exist on the release branch, stop and ask the user how to proceed (skip, adapt, or pull in additional commits) — do not silently rewrite the fix.
Phase 4 — Regenerate derived files (only if applicable)
Check whether the cherry-pick touches things that require regeneration. CI will fail otherwise (check-clog.yml, check-dotnet.yml).
- Trace / log macro changes (
QuicTraceLogInfo,QuicTraceEvent,
etc., or anything under src/manifest/): ``powershell ./scripts/update-sidecar.ps1 ` Commit any changes under src/generated/ and src/manifest/clog.sidecar` as part of the same commit (or amend).
- Public C API surface changes (anything under
src/inc/, especiallymsquic.h):
``powershell ./scripts/generate-dotnet.ps1 ` Commit any changes under src/cs/`.
If neither applies, skip this phase.
Phase 5 — Build and run tests locally (REQUIRED)
Build and run tests locally before pushing. This is required for every cherry-pick, regardless of whether the git cherry-pick was clean or required conflict resolution. Do not skip this phase.
- Build with the default TLS provider for the platform you're on:
``powershell ./scripts/build.ps1 -Tls schannel # Windows pwsh ./scripts/build.ps1 -Tls openssl # Linux ``
- Run the tests that exercise the cherry-picked code. Use a
GoogleTest --Filter to keep the runtime short: ``powershell ./scripts/test.ps1 -Tls schannel -Filter '<TestSuite>.<TestPattern>*' `` At minimum, run:
- the tests that were added or modified by the cherry-pick, and
- the tests directly covering the changed code paths (e.g.
TlsTest.* for src/platform/tls_*, ApiTest.* for src/inc/ surface changes, HandshakeTest.* for src/core/ handshake logic).
- If the build or the relevant tests fail on the release branch but
pass on main, stop and ask the user — do not push a broken cherry-pick. Likely causes: missing prerequisite commits, API drift between branches, or test infra changes that didn't get back-ported.
Capture the build and test outcome (pass/fail, number of tests run) to mention briefly when you ask for permission to push.
Phase 6 — Push and open the PR (gated on explicit user permission)
Stop here and show a summary of the cherry-pick to the user: original PR, target branch, branch name, PR title, build and test status. Confirm with the user before pushing. Then:
- Push the branch:
``powershell git push -u origin <user>/cp_<short_desc>_2_5_copilot ``
- Open the PR as a draft (per the user's standing rule, unless they say otherwise):
``powershell gh pr create --repo microsoft/msquic --base release/2.5 --head <user>/cp_<short_desc>_2_5_copilot --draft --title "[CP] <Original title> (#<orig_pr>)" --body-file <path_to_body.md> ```
--basemust be the release branch (release/2.4,release/2.5, …), notmain.
- If cherry-picking to multiple release branches, repeat phases 2–6 for each branch. Open one PR per branch; mention the sibling PR number in each body so reviewers can correlate them (e.g.
Companion PR for release/2.4: #5944).
Self-Verification Checklist
Before telling the user the cherry-pick is ready:
- [ ] PR
--baseis the correctrelease/X.Ybranch (nevermain). - [ ] PR title is
[CP] <orig title> (#<orig_pr>)(or an explicitly approved variant). - [ ] PR body uses the exact body of the original PR verbatim with no additions.
- [ ] Branch name follows
<user>/cp_<short_desc>_<X_Y>_copilot. - [ ] PR is opened as a draft.
- [ ] Only the cherry-picked commit (+ optional minimal build-fix commits) is on the branch — no unrelated changes.
- [ ] Local build succeeded on the release branch with the cherry-pick applied (Phase 5).
- [ ] Relevant tests were run locally and pass (Phase 5). The exact test filter and result are mentioned when asking the user for permission to push.
- [ ] If trace/log macros were touched →
scripts/update-sidecar.ps1was run and generated files committed. - [ ] If
src/inc/public headers were touched →scripts/generate-dotnet.ps1was run and generated files committed. - [ ] You obtained explicit user permission before pushing and opening the PR.
Anti-Patterns to Avoid
- Don't cherry-pick a PR that isn't merged on
mainyet. - Don't use
git cherry-pick -x— the project doesn't include
(cherry picked from commit X) trailers in the final commit message.
- Don't bundle unrelated fixes into the same cherry-pick PR. If you
see a related-but-distinct issue, open a separate cherry-pick.
- Don't invent a new title prefix (e.g.
[BACKPORT 2.5]) — stick to
[CP] to stay consistent with the last ~2 years of cherry-pick PRs.
- Don't silently drop test changes.
- Don't rewrite, summarize, or paraphrase the original PR's
description. The body must contain the original PR's body verbatim without additions.
- Don't skip the local build / test step (Phase 5), even when the
cherry-pick applied with no conflicts. Auto-merged hunks can still produce subtly wrong code.
- Don't push or open a PR without explicit user permission.
- Don't bump the version number as part of a cherry-pick PR —
version bumps (Bump version to v2.5.X) are separate PRs done at release time.
Non-Goals
- Triaging whether a fix should be cherry-picked. The user decides
that; this skill just executes the cherry-pick cleanly.
- Releasing / tagging / publishing artifacts. Those are separate
processes handled outside this skill.