Agent skill

PR Merge

by symfony in symfony/symfony

Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first.

MITAuto-check passedDevelopment

Install PR Merge

skills CLI
$ npx skills add symfony/symfony --skill pr-merge -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install symfony/symfony pr-merge --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/symfony/symfony.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/pr-merge .claude/skills/pr-merge && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
pr-merge
GitHub stars
31k
Token cost
~3.1k tokens
SKILL.md length
1,577 words
Files
1
Skills in repo
9
Repo updated
First seen
Licence
MIT

At a glance

Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first.

  • Works in 12 steps: Preconditions. The working tree is clean… → Update the branches. The local branch… → Fetch the PR head into a local pull/… → …
  • Asked to merge a PR
  • SKILL.md covers Confirmation rule, The merge commit, Categories and Gates, plus 4 more sections
  • Calls git and gh

What it does

PR Merge is an agent skill from symfony/symfony. Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first. Use when asked to merge a PR, to finish a merge that stopped on conflicts, or to verify that a merge was done right.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Pull requests and Human-in-the-loop approvals. It works with Symfony and PHP. The repository describes itself as: The Symfony PHP framework. The licence is MIT.

When your agent uses it

  • Asked to merge a PR
  • Finish a merge that stopped on conflicts
  • Verify that a merge was done right

Example prompts

  • “/pr-merge”

Workflow steps

12 steps, taken from the first numbered list in SKILL.md.

  1. Preconditions. The working tree is clean for tracked files
  2. Update the branches. The local branch must not have diverged
  3. Fetch the PR head into a local pull/ branch
  4. Squash when warranted. A multi-commit PR from a single contributor is
  5. Retarget when merging into another branch than the PR asked
  6. Build the message from the template above and write it to a file.
  7. Merge without committing
  8. Commit with the prepared message: git commit --file=.
  9. Attach the notes (skip for security merges and comment-less PRs)
  10. Validate. Run the test suites of the touched components
  11. Stop for the single confirmation described at the top: present the
  12. Sync the PR on GitHub when the head was rewritten (squashed or

What it can do on your machine

Read from SKILL.md and the folder at commit 31ed3bf. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • git
    • gh

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use git and gh, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

PR Merge loads about 3.1k tokens when it runs. Until then it costs about 77 tokens; SKILL.md has 1,577 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~77
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from symfony/symfony at commit 31ed3bf, republished under its MIT licence (© symfony). 1,577 words, ~3,052 tokens.

Download SKILL.mdSave it as .claude/skills/pr-merge/SKILL.md (or your agent's skills folder).
name
pr-merge
description
Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first. Use when asked to merge a PR, to finish a merge that stopped on conflicts, or to verify that a merge was done right.

Merging a pull request

Every pull request lands as exactly one --no-ff merge commit on the target branch, even a single-commit PR. The first-parent history therefore reads as one line per PR, the inner commits keep the contributor's authorship, and the merge commit archives the PR: its number, title, contributors, description and commit list in the message, and the PR comments in a git note. The repository stays self-contained: the history explains itself without GitHub.

This skill states the full process: run it end to end, resume it after a conflict, or use it to verify a merge. Do all the local work first, then stop exactly once for confirmation before anything outward happens.

This skill starts where pr-review-merge-prep ends: the PR has been reviewed, targets the right branch and is merge-ready. After a merge into an older maintained branch, merge-up carries it to the newer branches.

Confirmation rule

Merging publishes: it pushes upstream, edits the PR and comments on it. Everything up to and including the local merge commit is reversible, so do it without asking. Then stop once, before the first outward action, with a summary: target branch, suggested category and why, squash decision, CI verdict with the failures triaged, the linked issues that will be closed, and any gate that needs an override. One confirmation covers all the outward steps that follow. Treat anything but an explicit affirmative as no, and never bury a blocker in the summary.

The merge commit

{category} #{number} {title} ({contributors})

This PR was merged into the {branch} branch.

Discussion
----------

{PR title}

{PR body}

Commits
-------

{output of: git log {target}..pull/{N} --oneline}
  • {category} is one of feature, bug, minor, security, tidy (see below). The head line is load-bearing: release and changelog tooling parse it, and maintainers grep history for bug #, feature # and PR numbers.
  • {contributors} is the comma-separated list of unique commit authors, in commit order, GitHub login preferred, raw author name as fallback.
  • The second line varies:
    • squashed: This PR was squashed before being merged into the {branch} branch.
    • retargeted: This PR was submitted for the {asked} branch but it was merged into the {branch} branch instead.
    • retargeted and squashed: This PR was submitted for the {asked} branch but it was squashed and merged into the {branch} branch instead.
  • Security releases: the head becomes security #cve-XXXX-NNNNN {title} ({contributors}) and the message stops after the branch line. No Discussion, no Commits, no notes: the details stay out of the repository until the advisory is public.
  • Every @login in the message is wrapped in backticks, so pushing the commit does not ping the people mentioned in the discussion.
  • The PR comments are attached to the merge commit as a git note under refs/notes/github-comments, one block per comment: by {login} at {created_at} followed by the body. Skip bot comments: carsonbot and the CI bots add nothing worth archiving.

Categories

The category decides whether the change appears in the CHANGELOG and triggers a release. Suggest one yourself from the diff and the discussion, with a one-line reason, as part of the pre-push summary; the user corrects it there when needed.

CategoryMeaning
featureNew feature, merged into the dev branch only
bugBug fix, merged into the oldest affected maintained branch
minorNoteworthy change that is neither (new translations, generic types); still listed and released
securitySecurity fix with a CVE, merged during a coordinated release
tidyNot worth a release: coding standards, CI, typos, test-only fixes

Some satellite repositories (ux, ai, twig, reprise) add documentation.

Gates

Check these while preparing the merge and put the results in the pre-push summary. Overriding a failed gate is always the user's decision, never the skill's.

  • Core team approval: at least two +1 and no standing -1 among core team members, counting GitHub reviews (approved is +1, changes requested is -1) and comment votes (+1, -1, thumbs emoji). Votes by the PR author do not count. The merger's own approval counts as one of the two when the merger is on the team and did not author the PR.
  • Milestone matches the target branch: a version milestone names the branch the fix must land in (resolved through symfony.com/releases). On a mismatch, either fix the milestone or retarget the merge (step 5).
  • The branch is still maintained: no merging into a branch past end of maintenance without an explicit decision.
  • CI: check it in the background. It needs nothing from the working tree, so start it first (gh pr checks <N>, or the statuses and check runs on the head SHA) and let it run while the other steps proceed. Triage every failing job before the summary: a failure caused by the PR is a blocker to report with evidence, a pre-existing or unrelated failure is noted and moved past. fabbot and the static-analysis jobs are known false-positive producers; ignoring them is fine when what they flag is unrelated to the PR. Required checks still pending mean the verdict is not in yet. One confirmation covers all jobs; never ask per job.

Check the rest with gh pr view <N> --json reviews,milestone,baseRefName.

Show full SKILL.md (864 more words)Show less

The procedure

REMOTE is origin here. TARGET is the branch being merged into, ASKED the PR's base branch; they differ only when retargeting.

  1. Preconditions. The working tree is clean for tracked files (git status --porcelain --untracked-files=no prints nothing). Start the CI gate check in the background now.

  2. Update the branches. The local branch must not have diverged:

    bash
    git fetch $REMOTE
    git checkout $TARGET && git merge --ff-only $REMOTE/$TARGET
    # when retargeting, the same for $ASKED
  3. Fetch the PR head into a local pull/<N> branch:

    bash
    git fetch -f $REMOTE refs/pull/$N/head:pull/$N
  4. Squash when warranted. A multi-commit PR from a single contributor is squashed by default (branch-update merge commits made through the GitHub UI do not count as a second contributor). A multi-author PR is merged unsquashed to keep each author's commits, unless the commits carry no meaning and the user agrees to squash across authors. A PR that contains merge commits cannot be merged unsquashed: squash it, or rebase the merge commits away first. The squashed commit keeps the first commit's author and author date, and takes the PR title as its message:

    bash
    git checkout pull/$N
    base=$(git merge-base $ASKED pull/$N)   # the PR is still based on $ASKED at this point
    first=$(git rev-list $base..pull/$N | tail -1)
    last=$(git rev-list $base..pull/$N | head -1)
    author=$(git log -1 --format='%an <%ae>' $first)
    date=$(git log -1 --format=%ad $first)
    git reset --hard $first~
    git merge --squash $last
    git commit -m "$PR_TITLE" --author="$author" --date="$date"
  5. Retarget when merging into another branch than the PR asked:

    bash
    git rebase --onto $TARGET $ASKED pull/$N

    Remember that retargeting is a rewrite, not a copy: the review skill's rules on expressing the fix in the target branch's shape apply.

  6. Build the message from the template above and write it to a file. Generate the Commits section now, from the final shas: git -c color.ui=false log $TARGET..pull/$N --oneline.

  7. Merge without committing:

    bash
    git checkout $TARGET
    git merge --no-ff --no-commit pull/$N
  8. Commit with the prepared message: git commit --file=<message file>.

  9. Attach the notes (skip for security merges and comment-less PRs):

    bash
    git fetch -f $REMOTE refs/notes/github-comments:refs/notes/github-comments
    git notes --ref=github-comments add --file=<notes file>
  10. Validate. Run the test suites of the touched components (./phpunit src/Symfony/Component/<Name>) whenever the merge involved a rebase, a squash with conflicts, or anything beyond what CI already ran.

  11. Stop for the single confirmation described at the top: present the summary, collect the CI verdict from the background check, and get one go-ahead for everything that follows.

  12. Sync the PR on GitHub when the head was rewritten (squashed or retargeted), before the upstream push, so GitHub can mark the PR merged instead of closed. Only possible when the PR allows maintainer edits; otherwise skip, and the PR will show as closed. When retargeted, change the PR base first (gh pr edit $N --base $TARGET), then force-push the rewritten head to the contributor's fork, guarded by the head SHA the PR had:

    bash
    git push --no-follow-tags --force-with-lease=$HEAD_BRANCH:$OLD_HEAD_SHA $FORK_SSH_URL pull/$N:$HEAD_BRANCH

    This is the only force-push in the whole process, and it never targets the upstream repository. If it fails, restore the PR base.

  13. Clean up and push:

    bash
    git branch -D pull/$N
    git push --no-follow-tags $REMOTE $TARGET refs/notes/github-comments

    Leave refs/notes/github-comments out when no note was added.

  14. Close the loop on GitHub. Thank the author with a one-line comment (skip when the merger authored the PR, or for bots). Close the linked issues: the Issues row of the PR header table (Fix #NNNNN) and closing keywords in the body name them. GitHub auto-closes them only when the merge lands in the default branch, which is the dev branch here; a merge into any other branch leaves them open, so close each one with a short comment naming the PR and branch that fixed it. For a feature merged into symfony/symfony, open an issue on symfony/symfony-docs, milestoned to the target version, linking the PR and its authors, unless the PR body already links a real docs PR.

Conflicts and amending

  • To amend the PR before merging (a review fix, a changelog line), pause after step 5 on the pull/<N> branch, amend there, then continue with step 6.
  • When step 7 conflicts and the PR is editable, abort the merge and rebase pull/<N> onto the target instead: conflicts get resolved in the PR's own commits, and the recorded merge stays conflict-free. Then redo step 7.
  • When the PR is not editable, resolve inside the merge by hand and continue.
  • Amendments follow pr-review-merge-prep: keep the contributor's authorship, amend into their commits, never a placeholder identity.

Verify before pushing

bash
git show -s --format=%B HEAD                        # message matches the template, category exact
git log -1 --format='%an <%ae> / %cn <%ce>' HEAD    # merger as author and committer of the merge commit
git log --first-parent --oneline $REMOTE/$TARGET..$TARGET   # exactly one new first-parent commit
git notes --ref=github-comments show HEAD           # notes attached, when expected

The inner commits must keep the contributor as author. The committer of rewritten inner commits is the merger; that is expected.

Hard rules

  • Never force-push to the upstream remote, never rewrite the target branch. A merge adds exactly one merge commit on top of it.
  • Never merge with a plain git merge: without the prepared message, the archive value of the commit is lost and tooling cannot classify it.
  • Never push with --follow-tags; local tags stay local.
  • Never decide an override (a PR-caused CI failure, missing votes, an unmaintained branch, a milestone mismatch, an unsquashable PR) without asking; surface it in the pre-push summary.

© symfony, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/pr-merge of symfony/symfony.

Open the folder on GitHubat commit 31ed3bf

Compare with similar skills

PR Merge next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

PR Merge compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
PR Merge this skillsymfony/symfony31k—~3.1kAutomated safety check: PassMIT
WooCommerce Code Reviewwoocommerce/woocommerce11k3 repos~1.1kAutomated safety check: PassCustom licence
PR Review Merge Prepsymfony/ux1.1k—~4.6kAutomated safety check: PassMIT
Address PR Comments CecilCecilapp/Cecil298—~475Automated safety check: PassEUPL-1.2
Code Reviewpimcore/data-hub136—~1.6kAutomated safety check: PassCustom licence
Code ReviewerCaoMeiYouRen/caomei-auth220—~1.5kAutomated safety check: PassMIT

Similar skills

  • WooCommerce Code Review

    woocommerce/woocommerce

    Reviews WooCommerce code changes against the project's standards, flagging backend PHP architecture, naming, documentation, data integrity and testing violations.

    11k GitHub starsUsed in 3 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Principles for rigorously reviewing a Symfony UX pull request and making it merge-ready.

    1.1k GitHub stars~4.6k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Standard workflow to address pull request review comments in Cecil.

    298 GitHub stars~475 tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Code Review

    pimcore/data-hub

    Evidence-first review of Pimcore pull requests — judge against a fixed review contract, hold fixes to the Pimcore quality bar, and enforce the house PHP coding guidelines.

    136 GitHub stars~1.6k tokensUpdated today
    DevelopmentAuto-check passed
  • Code Reviewer

    CaoMeiYouRen/caomei-auth

    审查当前 git 变更、PR、提交范围、技能定义文件、架构调整或安全敏感代码时使用。输出结构化 Review Gate 结论(Pass/Reject)、问题分级(blocker/warning/suggest)、最低验证矩阵、证据链与复查基线。覆盖正确性、安全、架构、SOLID、可删除代码、性能、异常处理与测试风险;默认只输出 review,不直接修改代码。用户提到 review、code…

    220 GitHub stars~1.5k tokensUpdated 9 days ago
    DevelopmentAuto-check passed
  • Create PR

    inkline/inkline

    Author a pull request in the Guild's standard shape — a fixed Summary / Changes / Verification / Notes skeleton that mirrors the review-gate, plus the hard anti-leak rule that no agent @mention or…

    1.5k GitHub stars~1.7k tokensUpdated 28 days ago
    DevelopmentAuto-check passed

More from symfony/symfony

All 9 skills in this repo
  • Sync Translations

    symfony/symfony

    Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch…

    31k GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Bug Triage

    symfony/symfony

    Decide whether open Bug PRs target the correct branch. An agent skill from symfony/symfony.

    31k GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Merge Up

    symfony/symfony

    Cascade-merge maintained Symfony branches from oldest to newest (e.g.

    31k GitHub stars~4k tokensUpdated today
    Auto-check passed
  • Security Triage

    symfony/symfony

    Triage a reported security finding into a disposition: a private CVE (coordinated disclosure + advisory), a public hardening PR (fix in the open, no CVE), or not-a-security-issue (reply to reporter).

    31k GitHub stars~2.6k tokensUpdated today
    Auto-check passed
  • Review a change (a PR, the current branch diff, or a set of files) or audit a component or the whole tree for missing or incorrect security hardening.

    31k GitHub stars~2.9k tokensUpdated today
    Auto-check passed
  • Hardening Rule

    symfony/symfony

    Decide whether a recurring hardening invariant is worth a CI gate, and add it without hitting the traps.

    31k GitHub stars~1.2k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about PR Merge

What does PR Merge do?

Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first. PR Merge is an agent skill from symfony/symfony. Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first.

When should I use PR Merge?

PR Merge fits situations like: asked to merge a PR; finish a merge that stopped on conflicts; verify that a merge was done right.

How do I install PR Merge in Claude Code?

Run `npx skills add symfony/symfony --skill pr-merge -a claude-code`. Or copy the skill folder (.agents/skills/pr-merge in symfony/symfony) into .claude/skills/pr-merge in your project. Claude Code loads it when a task matches its description.

How do I install PR Merge in Codex?

Run `npx skills add symfony/symfony --skill pr-merge -a codex`. Or copy the skill folder (.agents/skills/pr-merge in symfony/symfony) into .agents/skills/pr-merge in your project. Codex loads it when a task matches its description.

Can I use PR Merge in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add symfony/symfony --skill pr-merge -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/pr-merge, .gemini/skills/pr-merge, .github/skills/pr-merge and .opencode/skills/pr-merge in your project.

What does PR Merge need to run?

Going by SKILL.md and its folder, PR Merge needs the command-line tools its instructions call (git and gh).

Does PR Merge access the network?

SKILL.md contains no URLs. Its commands use git and gh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is PR Merge safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does PR Merge use?

PR Merge is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does PR Merge use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to PR Merge?

Skills that share tags, products or a category with PR Merge: WooCommerce Code Review (woocommerce/woocommerce, 11k stars), PR Review Merge Prep (symfony/ux, 1.1k stars), Address PR Comments Cecil (Cecilapp/Cecil, 298 stars) and Code Review (pimcore/data-hub, 136 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains PR Merge?

symfony (a GitHub organization) maintains it in symfony/symfony, which has 31,182 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on October 9, 2026.

Source: symfony/symfony on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.