Skip to main content

backport

Backports a merged pull request from `main` onto a patch-release branch, e.g. `5.0.x`. Activates on `/backport <PR-number> [target-branch]`, and whenever the user asks to backport, port, or cherry-pick a merged PR, commit, or fix onto a patch, release, or maintenance branch, including phrasings like "backport #1234 to 5.0.x", "cherry-pick that fix onto 5.0.x", or "get this into the next patch release". Not for forward-porting onto `main`!

来源信息

仓库
DependencyTrack/frontend
最近来源活动
2026年8月24日 12:26
检测到的 SKILL.md 语言
英语
星标
172
分支
257

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
backport
description
Backports a merged pull request from `main` onto a patch-release branch, e.g. `5.0.x`. Activates on `/backport <PR-number> [target-branch]`, and whenever the user asks to backport, port, or cherry-pick a merged PR, commit, or fix onto a patch, release, or maintenance branch, including phrasings like "backport #1234 to 5.0.x", "cherry-pick that fix onto 5.0.x", or "get this into the next patch release". Not for forward-porting onto `main`!
allowed-tools
Bash, AskUserQuestion, Read, Edit
# Backporting a Pull Request Automates the patch-release backport flow from [`RELEASING.md`](../../../RELEASING.md) §Patch Releases. Invoke as: ``` /backport <PR-number> [target-branch] ``` Requires an authenticated [`gh`](https://cli.github.com/) CLI (`gh auth status`). ## Rules (DO NOT VIOLATE) - **Never** `git push`. Print the push command at the end and let the user run it. - **Never** add `Co-Authored-By: Claude ...` to any commit. - **Always** cherry-pick with `git cherry-pick -x -s` (records origin SHA, adds signoff, matches existing patch-branch history). - **Always** work in `.claude/worktrees/backport-pr-<N>`, never in the primary checkout. - **Never** hand-format code. If a resolution touches source, run `npm run prettier-fix` before committing. - If a conflict cannot be resolved unambiguously and does not apply conceptually, ask the user via `AskUserQuestion`. DO NOT IMPROVISE. ## Resolving the canonical remote `origin` may point at a fork. Resolve the canonical remote once and use `$CANON` everywhere below: ```sh CANON=$(git remote -v | awk '/DependencyTrack\/frontend.*\(fetch\)/ {print $1; exit}') ``` If empty, ask the user which remote tracks the canonical repo. ## Workflow ### 1. Validate state - Confirm CWD is the primary repo (not already a worktree). - Resolve `$CANON` per §Resolving the canonical remote, then `git fetch $CANON`. - If `target-branch` was omitted, derive it from the PR's backport label: ```sh gh pr view <N> --json labels -q '.labels[].name | select(startswith("backport/"))' ``` If `backport/5.0.5`, the target branch is `5.0.x`. On zero or multiple matches, ask the user via `AskUserQuestion`, offering branches matching `[0-9]+\.[0-9]+\.x`. ### 2. Locate the PR's commits ```sh gh pr view <N> --json state,baseRefName,mergeCommit ``` - `state` is not `MERGED`: abort. DO NOT GUESS. - `baseRefName` is not `main`: tell the user which branch the PR targeted and ask before continuing. (`master` still exists on the remote but is stale. Treat it like any other unexpected base.) Take `MERGE` from `mergeCommit.oid`, then check how it was merged: ```sh git rev-parse --verify --quiet "${MERGE}^2" ``` - **Merge commit** (`^2` resolves): the PR's commits are preserved in `main`. ```sh git log --reverse --format=%H "${MERGE}^1..${MERGE}^2" # oldest first ``` - **Squash or rebase merge** (`^2` missing): `MERGE` itself is the only commit to pick. ### 3. Set up the worktree Path: `.claude/worktrees/backport-pr-<N>` (in-tree, git-ignored). - **Reuse** (path exists, worktree registered): `cd` in, verify `git status` is clean (else ask the user), then `git checkout -B backport-pr-<N> $CANON/<target-branch>`. - **Fresh**: `git worktree add -b backport-pr-<N> .claude/worktrees/backport-pr-<N> $CANON/<target-branch>`. - **Leftover branch** (worktree gone, branch remains, `git worktree add` errors with `a branch named '…' already exists`): glance at `git log backport-pr-<N> ^$CANON/<target-branch>` to confirm nothing valuable, `git branch -D backport-pr-<N>`, retry. - If `git worktree add` half-succeeded (partial directory plus a stale branch), delete both and `git worktree prune` before retrying. A fresh worktree has no `node_modules`. Only install (§6) if a check actually needs it. ### 4. Apply each commit For each SHA from step 2, in order. First, skip what is already there: ```sh git log $CANON/<target-branch> --grep="cherry picked from commit <sha>" --format=%H ``` Non-empty means already backported. Skip it and note that in the summary. Otherwise `git cherry-pick -x -s <sha>`. - **Clean**: continue. - **Trivial conflict** (import order, non-overlapping adjacent edits): resolve, `git add`, `GIT_EDITOR=true git cherry-pick --continue` (`--continue` opens `$EDITOR` and hangs otherwise). - **Non-trivial but conceptually applies**: `git cherry-pick --abort`, recreate manually, commit per §Manual commit format. - **Does not apply conceptually** (target refactored/removed): `git cherry-pick --abort`, then `AskUserQuestion` with options (skip / reduced port / port differently). DO NOT INVENT A RESOLUTION. #### Inspecting a conflict before resolving Conflict markers can include unrelated `main`-only lines that anchored the hunk's context. Naively accepting "incoming" smuggles those into the backport. Before resolving, run `git show <sha> -- <conflicted-file>` to show the authoritative diff. If the `>>>>>>>` side has extra lines `git show` doesn't list, drop them. #### Locale files `src/i18n/locales/*.json` conflict constantly. Keys are sorted alphabetically and every locale carries every key. Resolve per key, not per hunk: - Take only the keys the picked commit actually adds or changes, leave the rest at the target branch's state. - A new key goes into `en.json` with its English value and into **every** other locale file with a `null` value. - Run `npm run prettier-fix` afterwards to restore key order and formatting. ### 5. Manual commit format For manually-recreated commits (not cherry-picked): - Mirror the original subject + body. - Add `Co-Authored-By: <Name> <email>` for the original commit's author. Omit if that email equals `git config user.email`. Never add `Co-Authored-By: Claude ...`. - `git commit -s` (adds `Signed-off-by`). Author identity = default git config. Pass the message via HEREDOC. ### 6. Post-backport checks Run from the worktree. Anything beyond the first row needs dependencies first: `npm ci` (uses the target branch's `package-lock.json`, never copy or symlink `node_modules` from the primary checkout, the lockfiles differ across branches). | If any commit touches | Run | | ------------------------------------------- | --------------------------------------- | | nothing but `.github/**`, `docker/**`, docs | nothing | | `src/i18n/locales/**` | `npm run vue-i18n-extract` | | `src/**`, `package.json`, `*.config.js` | `npm run prettier` then `npm run build` | `npm run eslint` is covered by [`lint.yaml`](../../../.github/workflows/lint.yaml) in CI and is slow locally. Run it only if a resolution changed non-trivial logic. On failure, report and stop. ### 7. Summary Print, in this order: 1. The worktree path. 2. One row per commit from step 2. Every commit gets a row, including skipped ones: | Status | Commit | Subject | | ------------------------------------------- | ------------- | ------- | | `picked` / `manual` / `skipped` / `already` | `<short-sha>` | ... | `<short-sha>` is the source commit on `main`, not the new one. For `skipped`, give the reason. 3. The push command (DO NOT RUN IT): ```sh cd .claude/worktrees/backport-pr-<N> && git push -u origin backport-pr-<N> ``` If any row is not `picked`, state that on one line above the table.
在 GitHub 查看