| name | merge-conflict-resolving |
| description | You resolve merge conflicts in code repositories, ensuring that the final merged code is functional and free of errors, and adheres to our code quality standards. |
Merge Conflict 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 with the conflict details and the branch must be fixed locally.
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 status locally 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
git merge origin/release/X.X.x
Lock Files (common/config/rush/pnpm-lock.yaml)
Always regenerate. Never manually edit.
rush update
rush update --full
Commit with: git commit -m "resolve pnpm-lock conflicts"
Examples: PR #8902, PR #8954
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
globalOverrides or ignoreCves)
- 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 update after editing package.json
API Signature Files (common/api/*.api.md)
Always regenerate. Never manually edit.
These files track the public API surface and are generated by rush extract-api. They conflict when the release branch has a different API surface than master.
rush build
rush extract-api
Also regenerate the export summary files: common/api/summary/*.exports.csv
Example: PR #8986 — backport of integrityCheck() modified common/api/core-backend.api.md
Rush Change Files (common/changes/@itwin/)
Rush change files are JSON files in common/changes/@itwin/<package>/ created by rush change. They usually have unique filenames and rarely conflict.
If they do conflict: Keep both files. If the same file has conflicts, merge the JSON content.
If change files are needed for the backport: Generate them non-interactively:
rush change --verify -b origin/release/X.X.x
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:
ls docs/changehistory/5.7.0.md
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.md empty — 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 in docs/changehistory/X.X.0.md.
- Determine the right section — look at the existing structure in
X.X.0.md and 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:
- Extract unique sections from both versions
- Merge into logical category order
- Update table of contents to match headers
- Remove duplicate content
Example: If one branch adds Electron support and another adds Presentation changes, include both sections in the proper order.
Verification
npx markdownlint docs/changehistory/NextVersion.md
rush docs
Avoid:
- Blindly merging master's
NextVersion.md content 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 status to see which files need resolution
-
Apply strategy:
- Lock file:
rush update → stage → commit
- pnpm-config.json: Edit manually →
rush update → stage both files → commit
- package.json: Edit manually →
rush update → stage both files → commit
- API files (common/api/):
rush build → rush extract-api → stage → commit
- Rush change files: Keep both / generate fresh → stage → commit
- NextVersion.md: Check if
X.X.0.md exists → Scenario A (keep empty, move to X.X.0.md) or B (merge both) → stage → commit
- CI/config files: Manual edit favoring release branch → stage → commit
-
Check for residual conflict markers:
grep -r "<<<<<<< " . --include="*.ts" --include="*.json" --include="*.md" --include="*.yaml" --include="*.yml"
-
Verify: Run rush build and ensure CI passes
-
Commit messages:
- 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"
Rollback
If resolution goes wrong:
git cherry-pick --abort
git reset --hard ORIG_HEAD
git clean -fd
rush update
Quick Reference
| File Type | Path | Resolution | Key Points |
|---|
| Lock file | common/config/rush/pnpm-lock.yaml | rush update | Never manually edit |
| 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 |
| API signatures | common/api/*.api.md | rush build + rush extract-api | Never manually edit |
| Rush change files | common/changes/@itwin/*/ | Keep both or regenerate | Usually unique filenames, rarely conflict |
| 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 |
For Automated Agents
- Check target branch first — Strategy differs for
master vs release/X.X.x
- Mergify uses cherry-pick — Recovery is
git cherry-pick --continue, not merge
- Parse structured data — Extract version fields from package.json programmatically
- Always check for conflict markers —
grep -r "<<<<<<< " . before committing
- Verify after resolution — Run
rush build, rush extract-api, and check git diff
- Never commit without testing — Ensure no syntax errors or breaking changes
- Reference the
cve-remediation skill — For understanding pnpm-config.json structure when resolving security backport conflicts