SuperAPI AI Directory

git-upstream-pr

General & other

View repository

Updated 10-15 23:49

About this skill

/git:upstream-pr

Submit clean, atomic PRs to upstream repositories from fork work.

When to Use This Skill

Use this skill when... Use something else instead when...
Contributing changes back to the upstream repo Committing to your own fork/repo → /git:commit
Cherry-picking fork commits for upstream PR (single or multi-commit, squashing) Creating a PR within the same repo → /git:pr
Fork and upstream are roughly aligned Fork has substantially diverged from upstream → /git:upstream-pr-diverged (patch-id eligibility, re-derive fallback, scrubbing)
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 -v
  • Origin URL: !git remote -v
  • Upstream URL: !git remote -v
  • 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

  1. Verify this is a git repository: git rev-parse --git-dir
  2. Check if upstream remote exists (from context)
  3. If no upstream remote:
    • 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
  4. Fetch upstream: git fetch upstream
  5. Record the current branch name and check for uncommitted changes
  6. 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

  1. Generate branch name if --branch not provided:
    • Extract scope from first commit message (e.g., feat(auth): add OAuth -> feat/auth-add-oauth)
    • Fallback: upstream-pr/<date>
  2. Create branch from upstream/main:
    git switch -c <branch-name> upstream/main
    

Step 5: Cherry-pick and squash

  1. Cherry-pick each selected commit in order:
    git cherry-pick <sha1> <sha2> ...
    
  2. If cherry-pick conflicts occur:
    • Report the conflict to the user
    • Reference git-conflicts for resolution
    • After resolution: git cherry-pick --continue
  3. Squash all cherry-picked commits into one atomic commit:
    git reset --soft upstream/main
    git commit -m "<conventional commit message>"
    
  4. 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

  1. Determine the upstream repo (from --upstream or detected remote)
  2. Determine the fork owner (from origin remote URL)
  3. Create the PR:
    gh pr create \
      --repo <upstream-owner/upstream-repo> \
      --base main \
      --head <fork-owner>:<branch-name> \
      --title "<conventional commit title>" \
      --body "<PR description>"
    
    Add --draft if the flag was provided.
  4. Report the PR URL to the user

Step 8: Restore working state

  1. Switch back to the original branch:
    git switch <original-branch>
    
  2. If changes were stashed in Step 1, pop them:
    git stash pop
    
  3. 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