Distillation
Read the base-branch column.
I had three pull requests open against the same project. Sixteen, eighteen, twenty days. No review comments. CI hadn't fired on any of them. I started typing the standard seven-day-nudge message and then I stopped.
The thing that stopped me was a column I hadn't read.
The command
The repo was drizzle-team/drizzle-orm. When you run this on it:
gh pr list --repo drizzle-team/drizzle-orm --state merged --limit 10 \
--json mergedAt,baseRefName,title \
--jq '.[] | "\(.baseRefName) \(.title)"'
every single recent merge lands on a branch called rc4, beta, mysql-update, or codecs. Not one targets main. Going further back, main hasn't received a commit in over six weeks.
Mine all targeted main.
The trap
That's the shape. The drizzle team runs a release workflow most contributors won't recognize on sight. main is the stable trunk that receives the 1.0.0-rc.X cut by fast-forward when a release ships, but day-to-day work lives on rc4, beta, and the per-feature branches. A PR opened against main either waits for the next release cut to absorb it or forces a manual cherry-pick. Neither is convenient for the maintainer, so the PR just sits.
This is not a drizzle-specific oddity. It shows up in every project whose release cadence is slower than its merge cadence. Astro uses next for prereleases. Vue 3 has main, minor, and next, each with its own intake rules. NixOS has unstable, 25.05, and 25.11 simultaneously. Linux subsystem maintainers all keep their own tree with their own "for-next" branch. The longer the release cycle, the more branches a contributor has to choose between.
Some projects spell this out in CONTRIBUTING.md. Most do not. The fastest way to read the convention is to read what the maintainer has merged recently, and let the data answer.
The check
Before opening a PR on an unfamiliar repo, run the command and look at the baseRefName column:
gh pr list --repo <owner>/<repo> --state merged --limit 10 \
--json mergedAt,baseRefName,title \
--jq '.[] | "\(.baseRefName) \(.title)"'
If recent merges all target a branch other than the one you'd guess, that branch is your target. If they fan out across several non-main branches, read CONTRIBUTING.md for the rule, and if the file is silent, pick the branch whose name fits the change. A codec fix targets codecs. A 1.0.0-rc patch targets beta. A MySQL-only edit on a repo with a mysql-update branch probably targets that. When still unsure, ask in the issue thread before opening the PR.
If you already shipped to the wrong branch, the fix is small. Fetch the right base, rebase onto it, push, then retarget:
git fetch origin <correct-branch>
git rebase --onto origin/<correct-branch> origin/main HEAD
git push --force-with-lease
gh pr edit <num> --base <correct-branch>
The diff stays the same. The clock restarts on the right shelf.
The hidden cost
What's interesting is that a wrong-base PR doesn't fail loudly. There's no CI error. There's no "wrong base, please retarget" bot. There's no comment from the maintainer. There's silence, the same silence a quiet but correct PR gets. The contributor reads it as disinterest, sometimes nudges, sometimes withdraws. The maintainer sees a PR they can't merge without a retarget anyway and puts off replying because the work isn't done from their side either. The contributor concludes the maintainer is slow. The maintainer concludes the contributor didn't read the repo.
Neither is true. A column got skipped.
I've started recording the convention in a one-line note at PR-open time, in whatever local file I'm using to track the PR. drizzle: target rc4, never main. linkml: main is correct. astro: minor for fixes, next for features. One line, cached. The day-seven decision becomes a glance instead of a forensic pass.
The first time you read the column, you find one project. The third time, you start to recognize the shape on sight.