git-upstream-pr
SKILL.md
/git:upstream-pr
Submit clean, atomic PRs to upstream repositories from fork work.
When to Use This Skill
| Use this skill when... | Use /git:commit instead when... |
|---|---|
| Contributing changes back to the upstream repo | Committing to your own fork/repo |
| Cherry-picking fork commits for upstream PR | Creating a PR within the same repo |
| Fork's main has diverged from upstream | Fork and upstream are in sync |
| Need a clean branch based on upstream/main | Working on a branch already tracking upstream |
Context
- Current branch: !
git branch --show-current - Git status: !
git status --porcelain=v2 --branch - Remotes: !
git remote -v - Has upstream: !
git remote get-url upstream - Origin URL: !
git remote get-url origin - Upstream URL: !
git remote get-url upstream - Recent commits: !
git log --oneline --max-count=20 - Stash list: !
git stash list
Parameters
Parse these from $ARGUMENTS:
| Parameter | Required | Description |
|---|---|---|
--commits sha1,sha2,... |
No | Comma-separated commit SHAs to cherry-pick (interactive selection if omitted) |
--branch name |
No | Name for the upstream PR branch (auto-generated if omitted) |
--upstream owner/repo |
No | Override upstream repo (detected from remote if omitted) |
--draft |
No | Create PR as draft |
--dry-run |
No | Show what would happen without making changes |
Execution
Execute this fork-to-upstream PR workflow:
Step 1: Validate fork environment
- Verify this is a git repository:
git rev-parse --git-dir - Check if
upstreamremote exists (from context) - If no
upstreamremote:- Try to detect via
gh repo view --json parent -q '.parent.nameWithOwner' - If found, add it:
git remote add upstream https://github.com/<owner/repo>.git - If not found, ask user with AskUserQuestion for the upstream repo URL
- Try to detect via
- Fetch upstream:
git fetch upstream - Record the current branch name and check for uncommitted changes
- If uncommitted changes exist, stash them:
git stash push -m "upstream-pr: WIP before upstream PR"
Step 2: Assess fork state
Report the fork's divergence from upstream:
Fork status:
Upstream: <upstream-repo>
Behind upstream/main: N commits
Ahead of upstream/main: M commits
If --dry-run is set, also show which commits would be selected and stop here.
Step 3: Select commits
If --commits provided:
- Parse the comma-separated SHA list
- Validate each SHA exists:
git rev-parse --verify <sha> - Show summary of selected commits
If --commits not provided:
- Show recent commits that are ahead of upstream/main:
git log --oneline --format='%h %s (%cr)' upstream/main..HEAD - Use AskUserQuestion to let the user select which commits to include
- Present commits as options with their subject lines
Step 4: Create clean branch from upstream/main
- Generate branch name if
--branchnot provided:- Extract scope from first commit message (e.g.,
feat(auth): add OAuth->feat/auth-add-oauth) - Fallback:
upstream-pr/<date>
- Extract scope from first commit message (e.g.,
- Create branch from upstream/main:
git switch -c <branch-name> upstream/main
Step 5: Cherry-pick and squash
- Cherry-pick each selected commit in order:
git cherry-pick <sha1> <sha2> ... - If cherry-pick conflicts occur:
- Report the conflict to the user
- Reference git-conflicts for resolution
- After resolution:
git cherry-pick --continue
- Squash all cherry-picked commits into one atomic commit:
git reset --soft upstream/main git commit -m "<conventional commit message>" - Use AskUserQuestion to confirm or edit the commit message
- Default message: derived from the cherry-picked commits
- Format: conventional commit with scope
Step 6: Push to fork
git push -u origin <branch-name>
If --dry-run, show the command without executing.
Step 7: Create cross-fork PR
- Determine the upstream repo (from
--upstreamor detected remote) - Determine the fork owner (from
originremote URL) - Create the PR:
Addgh pr create \ --repo <upstream-owner/upstream-repo> \ --base main \ --head <fork-owner>:<branch-name> \ --title "<conventional commit title>" \ --body "<PR description>"--draftif the flag was provided. - Report the PR URL to the user
Step 8: Restore working state
- Switch back to the original branch:
git switch <original-branch> - If changes were stashed in Step 1, pop them:
git stash pop - Report completion summary:
Upstream PR created: PR: <url> Branch: <branch-name> Commits: N cherry-picked, squashed into 1 Original branch restored: <branch>
Error Handling
| Error | Recovery |
|---|---|
| Cherry-pick conflict | Show conflicted files, reference git-conflicts skill |
| Push rejected | Check if branch already exists on fork; suggest --branch override |
| No upstream remote | Auto-detect from gh repo view --json parent or ask user |
| Upstream/main not found | Try upstream/master; ask user for correct branch name |
| No commits ahead of upstream | Report "Nothing to contribute" and exit |
Agentic Optimizations
| Context | Command |
|---|---|
| Divergence check | git rev-list --left-right --count upstream/main...HEAD |
| Commits ahead | git log --oneline --format='%h %s' upstream/main..HEAD |
| Validate SHA | git rev-parse --verify --short <sha> |
| Fork owner | git remote get-url origin | sed -E 's#.*github.com[:/]##; s#\.git$##; s#/.*##' |
| Upstream repo | git remote get-url upstream | sed -E 's#.*github.com[:/]##; s#\.git$##' |
| Cross-fork PR | gh pr create --repo <upstream> --head <fork-owner>:<branch> |
Related Skills
- git-fork-workflow - Fork management and sync strategies
- git-branch-pr-workflow - General branch and PR patterns
- git-conflicts - Resolve cherry-pick conflicts
- git-rebase-patterns - Advanced rebase techniques
- gh-cli-agentic - GitHub CLI cross-fork PR fields
Weekly Installs
17
Repository
laurigates/clau…-pluginsGitHub Stars
13
First Seen
12 days ago
Security Audits
Installed on
openclaw17
github-copilot17
codex17
kimi-cli17
gemini-cli17
cursor17