merge-conflict-resolver
npx skills add https://github.com/cesar-rodriguez/skills --skill merge-conflict-resolver
Agent 安装分布
Skill 文档
Merge Conflict Resolver
Resolves merge conflicts on GitHub PRs autonomously. Clones, rebases, resolves, tests, pushes.
Usage
Given: repo=owner/repo pr=96
1. Resolve merge conflicts on PR #96
2. Run tests to verify
3. Push if clean, bail if uncertain
Workflow
# 1. Setup
WORKDIR=$(mktemp -d)
cd "$WORKDIR"
gh repo clone "$REPO" . -- --depth=100
gh pr checkout "$PR"
PR_BRANCH=$(git branch --show-current)
TARGET_BRANCH=$(gh pr view "$PR" --json baseRefName -q .baseRefName)
# 2. Rebase
git fetch origin "$TARGET_BRANCH"
git rebase "origin/$TARGET_BRANCH" 2>&1 || true
# If no conflicts, we're done â push and exit
# 3. Detect & resolve conflicts (loop until rebase complete)
# For each conflicted file, classify and resolve (see Decision Tree)
# After resolving: git add <file> && git rebase --continue
# 4. Post-resolution fixups
# Go: go mod tidy (regenerates go.sum)
# Node: npm install (regenerates package-lock.json)
# 5. Test
# Auto-detect: go test ./... | npm test | make test
# Override with test_cmd input
# 6. Push or bail
# Success: git push --force-with-lease origin "$PR_BRANCH"
# Failure: report what happened, don't push
Conflict Decision Tree
Classify each conflicted file, then apply the matching strategy:
1. go.sum â AUTO-RESOLVE
- Accept either side (doesn’t matter which)
- Run
go mod tidyafter all conflicts resolved - Always safe â go.sum is deterministically regenerated
2. go.mod â AUTO-RESOLVE (careful)
- Keep both sides’ dependency additions
- Run
go mod tidyafter to clean up - Bail if: conflicting version constraints on same dependency
3. package-lock.json â AUTO-RESOLVE
- Accept either side
- Run
npm installafter all conflicts resolved - Always safe â regenerated from package.json
4. Go import blocks â AUTO-RESOLVE
- Use
scripts/resolve_go_imports.shon the file - Strategy: keep all imports from both sides, sort alphabetically within groups
- Preserves blank-line grouping (stdlib / external / internal)
- Always safe â duplicate imports cause compile errors caught by tests
5. Registration/init files (blank imports, init() calls) â AUTO-RESOLVE
- Pattern:
_ "github.com/org/repo/pkg"imports orRegister("name", ...)calls - Keep both sides’ additions, sort alphabetically
- Common in:
cmd/*/main.go,*_test.goTestMain, plugin registrations - Always safe â duplicates caught by compiler/tests
6. Generated files (.pb.go, *_gen.go, mock_*.go) â SKIP
- Accept theirs (target branch version)
- Will be regenerated by build if needed
- Bail if: no generation step available
7. Content conflicts â ANALYZE OR BAIL
This is the hard case. Analyze using merge base:
MERGE_BASE=$(git merge-base HEAD REBASE_HEAD)
git show "$MERGE_BASE:path/to/file" > /tmp/base.txt
# Compare: what did each side change relative to base?
Auto-resolve when:
- Changes are in non-overlapping sections that git failed to merge (adjacent lines)
- One side only added/removed whitespace
- One side is a strict superset of the other (keep the superset)
- Both sides made the identical change (keep either)
Bail when:
- Both sides modified the same logic differently
- Conflict involves control flow changes (if/else, switch cases)
- Conflict is in test assertions (changing expected values)
- You can’t determine intent from the diff alone
- More than 3 content conflicts in a single file
Bail-Out Protocol
When bailing:
git rebase --abort- Clean up temp dir
- Report:
- Which files had conflicts
- Which were auto-resolvable vs not
- For non-resolvable: show the conflict markers with context
- Suggested resolution if you have one (but don’t apply it)
Principle: Never push code you’re not confident about.
Language Detection
# Go project
[[ -f go.mod ]] && LANG="go"
# Node project
[[ -f package.json ]] && LANG="node"
# Both possible â check conflicted files to decide
Go-Specific Fixups
# After all conflicts resolved:
go mod tidy
goimports -w . # if available, otherwise gofmt -w .
go build ./... # quick sanity check
go test ./... # full test
Node-Specific Fixups
npm install # regenerate lockfile
npm run build # if build script exists
npm test
Real-World Patterns
These patterns come from actual sprint conflicts (sg-policy):
Pattern: Parallel imports
Scenario: Two PRs both add imports to the same file.
PR-A adds "sort", PR-B adds "strings".
Resolution: Keep both, sort alphabetically. Mechanical.
Pattern: Parallel registrations
Scenario: Two PRs both add adapter registrations (blank imports + init code). PR-A adds k8s adapter, PR-B adds GHA adapter. Resolution: Keep both registrations, sort imports, merge any shared code (help text, auto-detect arrays) by combining entries.
Pattern: Lock file divergence
Scenario: Two PRs both ran go mod tidy or npm install, creating different lock files.
Resolution: Accept either, re-run the lock command.
Integration with sprint-runner
When called from sprint-runner:
Input: repo, pr number, lane context (what the PR is doing)
Output: { resolved: bool, conflicts: [...], test_result: pass/fail, pushed: bool, bail_reason?: string }
Auto-Invocation Protocol
The sprint-runner automatically invokes this skill when:
- A PR’s
mergeablestatus isCONFLICTING(checked after each merge in the sprint) - A
git mergeorgh pr mergefails with conflict errors - A rebase attempt fails during lane execution
Detection loop (sprint-runner runs this after each PR merge):
for pr in $(remaining_open_prs); do
mergeable=$(gh pr view $pr --repo $REPO --json mergeable -q .mergeable)
if [[ "$mergeable" == "CONFLICTING" ]]; then
# Invoke merge-conflict-resolver with: repo, pr, test_cmd
fi
done
Retry Policy
- First attempt: Auto-invoke this skill with full context
- If bail (semantic conflict): Sprint-runner tries cherry-pick-to-new-PR:
- Create new branch from
main - Cherry-pick the PR’s commits
- Open replacement PR, close old one (pattern: PR #119 â #122 in sg-policy)
- Create new branch from
- If cherry-pick also fails: Escalate to human with:
- Which files conflict
- What each side changed
- Suggested resolution (if available)
- The lane is paused until resolution
Post-Merge Conflict Scan
After resolving a conflict, re-check all remaining open PRs â fixing one conflict can cascade (especially with shared import blocks or go.sum).
Lessons from Production
sg-policy Epic #114
- PR #119 had import block conflicts after parallel lane merges
- Auto-rebase failed â cherry-picked to replacement PR #122
- Lesson: Always re-scan all open PRs after merging any PR that touches shared files
Common Conflict Hotspots
go.sum/package-lock.jsonâ always auto-resolvable, always regenerate- Import blocks in Go files â keep both sides, sort, run goimports
- Registration/init files (blank imports) â keep both, sort alphabetically
- Hot files (high churn) â flag these in the execution plan for lane serialization