Backport Resolution
Resolve merge conflicts in backport PRs from Mergify. Mergify uses cherry-pick (not merge) to create backport branches with the pattern mergify/bp/release/X.X.x/pr-NNNN. When cherry-pick fails, Mergify comments that the PR is conflicted and the branch must be fixed locally.
This skill covers what is specific to backports. For the general per-file-type strategies — lock files, API reports, rush change files, source conflicts, modify/delete conflicts, conflict-marker checks, and the review gate — use the merge-conflict-resolving skill alongside this one. Where a file-type strategy there says merge both branches' content, the rule below wins on a release branch: keep the release branch side, and add only the change being backported.
Prerequisite: This skill references the cve-remediation skill for understanding pnpm-config.json structure (globalOverrides, ignoreCves). Load that skill when resolving conflicts in security-related backports.
How Mergify backports work
- A PR merges to
master - Mergify cherry-picks the commit(s) onto a new branch:
mergify/bp/release/X.X.x/pr-NNNN - If cherry-pick fails, Mergify marks the PR as conflicted and posts a generic comment (it does not list specific files — use
git statuslocally to identify conflicts) - A developer checks out the branch, resolves conflicts, and pushes
To start resolving:
git fetch origin
git checkout mergify/bp/release/X.X.x/pr-NNNN
git cherry-pick --continue # If mid cherry-pick
# OR
git merge origin/release/X.X.x # If syncing with target branch
pnpm-config.json Conflicts
File: common/config/rush/pnpm-config.json
This is the most common conflict file in security backports. It contains globalOverrides (dependency version overrides) and ignoreCves (audit exceptions). For detailed structure, see the cve-remediation skill.
Resolution Strategy
Keep all existing entries from the release branch (HEAD). Add new entries from the incoming change.
- Open the file and identify the conflicting sections (usually
globalOverridesorignoreCves) - Keep every existing override/exception from the release branch
- Add the new override/exception being backported from the incoming change
- Fix JSON syntax — especially trailing commas:
- The last entry in a JSON object must NOT have a trailing comma
- When adding a new last entry, add a comma to the previously-last entry
Example Resolution
Release branch (HEAD) has:
"globalOverrides": {
"cross-spawn": "^7.0.5",
"axios": "^1.13.5"
}
Incoming change adds serialize-javascript override:
"globalOverrides": {
"cross-spawn": "^7.0.5",
"axios": "^1.13.5",
"serialize-javascript": "^7.0.3"
}
After resolving, always run rush update to regenerate the lock file.
Examples: PR #9007, PR #9041, PR #9049
Package.json Conflicts in Backports
Rule: When backporting to release/X.X.x, keep the release branch's version information and only accept new functional changes.
Keep from Release Branch (HEAD)
- Version numbers:
"version": "5.5.0" - Internal workspace dependencies (this repo uses
workspace:*for internal deps — do not convert to hardcoded versions unless the release branch already uses them) - Branch-specific scripts and configurations
Accept from Incoming (master)
- New dependencies being added
- New scripts being added
- External dependency updates (if that's the purpose of the backport)
After resolving, always run rush update to regenerate the lock file.
Avoid:
- Accepting master's version numbers in release branches
- Forgetting to run
rush updateafter editing package.json
Rush Change Files in Backports
Rush change files rarely conflict, but if change files are needed for the backport, generate them non-interactively against the release branch:
rush change --verify -b origin/release/X.X.x
# If needed:
rush change --bulk --message "" --bump-type none -b origin/release/X.X.x
Example: PR #8345 — had 30+ rush change files for a multi-package backport
Documentation Conflicts (NextVersion.md)
Resolution depends on whether the target release branch has already shipped its initial release (X.X.0).
Detect: has X.X.0 already been released?
Check whether a version-specific changelog file already exists on the release branch:
# For a backport targeting release/5.7.x:
ls docs/changehistory/5.7.0.md
# Or check git tags:
git tag --list 'release/5.7.*'
If X.X.0.md exists (or the release/X.X.0 tag exists), the initial release has shipped and NextVersion.md on that branch should be empty.
Scenario A — Initial release has shipped (X.X.0.md exists)
On backport branches targeting release/X.X.x after the X.X.0 release, NextVersion.md on the release branch (HEAD) is intentionally empty. The incoming side from master will have content that was written for the next major/minor release — not for this patch branch.
Resolution:
- Keep
NextVersion.mdempty — resolve to the HEAD (release branch) side, which has only the frontmatter and heading:--- publish: false --- # NextVersion - Move relevant entries to
X.X.0.md— extract only the changelog entries that correspond to the change being backported (ignore unrelated master content like new features). Place them under the appropriate section indocs/changehistory/X.X.0.md. - Determine the right section — look at the existing structure in
X.X.0.mdand add the entry under the matching category (e.g.,## Display > ### Fixes). Create a subsection if needed.
What to discard: Any incoming NextVersion.md content that describes features or changes not being backported. These belong on master only.
Example: PR #9059 backport — incoming side had both a WithQueryReader feature (master-only) and a reality data fix (being backported). Only the fix was moved to 5.7.0.md.
Scenario B — Initial release has NOT shipped yet (no X.X.0.md)
NextVersion.md is still the active changelog for the upcoming release. Merge both versions intelligently, as described in the merge-conflict-resolving skill: extract unique sections from both, merge into logical category order, update the table of contents, and remove duplicate content.
Verification
rush docs # Ensure documentation builds
Avoid:
- Blindly merging master's
NextVersion.mdcontent into a post-release patch branch - Discarding backported changelog entries entirely — they must go into
X.X.0.md - Leaving mismatched table of contents (Scenario B)
- Keeping duplicate sections
CI/Config File Conflicts (.github/)
CI workflows and configuration files can diverge significantly between major release branches.
Common conflicting files:
.github/workflows/extract-api.yaml— node version, action versions.github/mergify.yml— backport target branches.github/workflows/*.yaml— CI pipeline changes
Resolution: Generally keep the release branch's CI configuration. Only accept incoming changes that are specifically being backported (e.g., a node version bump needed for compatibility).
Example: PR #9049 — needed additional edit to bump node version in extract-api.yaml for the older release branch
Source Code Conflicts (.ts files)
Rare in backports but possible when the same code area was modified on both branches.
Resolution:
- Understand the intent of the backported change
- Apply the functional change to the release branch's version of the code
- Do not blindly accept incoming — the release branch may have different surrounding context
Combined Backports
Sometimes Mergify cannot cherry-pick cleanly because multiple related changes need to land together. In this case, combine the changes into a single backport PR.
Example: PR #9007 — combined 3 separate PRs into one backport due to dependency conflicts
When combining:
- List all original PR numbers in the PR description
- Ensure all changes are compatible with each other on the release branch
- Sometimes backport-specific edits are needed beyond the original PRs
Resolution Workflow
Identify conflict type: Run
git statusto see which files need resolutionApply strategy (stage each resolved file with
git add; the operation is completed once in step 5, not per file):- pnpm-config.json: Edit manually →
rush update→ stage both files - package.json: Edit manually →
rush update→ stage both files - NextVersion.md: Check if
X.X.0.mdexists → Scenario A (keep empty, move toX.X.0.md) or B (merge both) → stage - CI/config files: Manual edit favoring release branch → stage
- Lock file, API files, rush change files, modify/delete: See the
merge-conflict-resolvingskill
- pnpm-config.json: Edit manually →
Check for residual conflict markers:
grep -r "<<<<<<< " . --include="*.ts" --include="*.json" --include="*.md" --include="*.yaml" --include="*.yml"Verify: Run
rush buildand ensure CI passesFinish the resolution — the command depends on the operation
git statusreports:Active cherry-pick (the normal Mergify backport case): stage the resolved files and continue — do not create a separate commit first, or the continue step becomes empty or duplicates the change:
git add <resolved files> git cherry-pick --continue # reuses the original commit messageMerge with the target branch (
git merge origin/release/X.X.x): stage and commit normally, using the messages below.
If a modify/delete conflict was resolved, stop for review before this step (see the review gate in the
merge-conflict-resolvingskill).Commit messages (for merge commits, or when amending the cherry-picked commit):
- Lock files:
"resolve pnpm-lock conflicts" - pnpm-config.json:
"resolve pnpm-config.json conflicts in backport" - Package.json:
"resolve package.json conflicts in backport" - API files:
"regenerate api files after backport" - Documentation:
"merge NextVersion.md from both branches" - Multiple files:
"resolve conflicts"
Push the backport branch:
git push
Completion Criteria
The backport is ready for review only when every box is checked:
-
git statusreports no unmerged paths and no cherry-pick still in progress -
grep -r "<<<<<<< " .returns nothing - The release branch's own versions, overrides, and CI config survived — only the backported change was added
-
rush updatewas run ifpnpm-config.jsonor anypackage.jsonwas edited, and the regenerated lock file is staged -
rush buildsucceeds andrush extract-apishows only expected API changes - Changelog entries landed in the right file:
X.X.0.mdif that release shipped, otherwiseNextVersion.md -
rush docssucceeds if any changelog file was touched - Every modify/delete resolution was summarized and explicitly approved by the user
- The branch is pushed and the backport PR references the original PR number(s)
Rollback
If resolution goes wrong:
# Abort an in-progress cherry-pick
git cherry-pick --abort
# Or reset to the last good state (before the cherry-pick)
git reset --hard ORIG_HEAD
git clean -fd
# Then re-attempt
rush update
Quick Reference
| File Type | Path | Resolution | Key Points |
|---|---|---|---|
| pnpm-config | common/config/rush/pnpm-config.json |
Manual edit + rush update |
Keep release entries, add new. See cve-remediation skill for structure |
| package.json | <package>/package.json |
Manual edit + rush update |
Keep release versions, add new deps only |
| Rush change files | common/changes/@itwin/*/ |
Generate with -b origin/release/X.X.x |
Verify against the release branch, not master |
| NextVersion.md | docs/changehistory/NextVersion.md |
See scenarios A/B | If X.X.0.md exists: keep empty, move entries to X.X.0.md. Otherwise: merge both. |
| CI/config | .github/workflows/*.yaml |
Manual edit | Favor release branch config |
| Source code | *.ts |
Apply backported intent to release branch | Do not blindly accept incoming |
For Automated Agents
- Check target branch first — Strategy differs for
mastervsrelease/X.X.x; this skill applies only to release branch targets - Mergify uses cherry-pick — Recovery is
git cherry-pick --continue, not merge - Do not
git commitduring an active cherry-pick — Stage the resolved files and rungit cherry-pick --continue; a manual commit first leaves the continue step empty or duplicated - Keep the release branch side — Anything in a conflict hunk that is not part of the change being backported stays as the release branch has it
- Parse structured data — Extract version fields from package.json programmatically
- Check whether
X.X.0.mdexists before resolvingNextVersion.md - Always check for conflict markers —
grep -r "<<<<<<< " .before committing - Verify after resolution — Run
rush build,rush extract-api, and checkgit diff - Never commit without testing — Ensure no syntax errors or breaking changes
- Reference the
cve-remediationskill — For understanding pnpm-config.json structure when resolving security backport conflicts - Reference the
merge-conflict-resolvingskill — For lock files, API reports, modify/delete conflicts, and the review gate