Skip to content

A pull request can only be tried against today's trunk, never as its author wrote it #290

Closed

Description

@juanmaguitar

Applying a pull request today means carrying its diff onto the current checkout. That answers one question: does this change still work against today's trunk? It is the cheap question — the clone, the installed dependencies and the build are all reused — and most of the time it is the right one.

It is not the only one a reviewer asks. Does the pull request work as its author wrote it? is a different question, and on the command line it has a different answer: fetch the pull request's branch and stand on it. That route cannot fail to apply, because nothing is applied — the tree simply becomes what the author tested. It is how contributors habitually try each other's work.

The app performs the first route silently and presents its failures as the pull request's. In the case that surfaced this (Trac #62064, via #282 and #226), the apply refused with conflicts; the branch itself was fine — seventeen months old, and exactly what its author meant to be tested. A contributor who only wanted to see the change running was charged for a question they had not asked.

What the option costs, and why the button must say so

Standing on a seventeen-month-old tree means a different lockfile and a different build: install and rebuild, minutes not seconds — and the same again on the way back to trunk. That is inherent to the question, not an implementation failure; the command line charges exactly the same. The app's job is to state the price before the click, not to hide the route because it has one.

What is plumbing and what is design

The plumbing exists: the bundled git implementation can fetch a pull request's ref at depth 1 and check it out. No git binary, no GitHub CLI, nothing new on the host — checked by hand against a real pull request.

The open part is the model, not the fetch. A site holds a pristine trunk and one branch per ticket (#108); a foreign branch is a third kind of thing. Where the contributor's parked work goes while they stand on it, what state the dev server and build watcher are in across the switch, and what "back" is called and shown as — those are design questions this issue leaves open on purpose.

Deliberately not proposed

Replacing the current apply. Onto-today's-trunk stays the default: it is the cheap route, and with the second half of #226 it stops failing for the wrong reasons. This issue is only about the other question existing at all, priced honestly, for the contributor who is asking it.

Trac attachments are out of scope — an attachment has no branch to stand on. This is a pull-request-only route.

Related

Activity

  1. juanmaguitar commented on Aug 13, 2026

    @juanmaguitar
    CollaboratorAuthor

    Closing as not planned for the current experimental validation phase. This remains a valid, searchable observation, but there is not enough user evidence or near-term intent to keep it in the active work queue. It can be reopened if real usage shows material impact.

  2. juanmaguitar commented on Aug 18, 2026

    @juanmaguitar
    CollaboratorAuthor

    Reopening under #350, on the condition the closing note set: the intent now exists. The design work behind #350 names standing on a pull request's branch as its first piece, and #349 needs the same foreign-ref plumbing for release branches — two consumers where there were none.

    Two additions to the scope as written here:

    Everything else in the body stands, the price-before-the-click rule especially.

  3. added
    real-world-gitCloser-to-real-Git experience: the interoperability contract (#350) and its pieces
    on Aug 18, 2026
  4. juanmaguitar commented on Sep 9, 2026

    @juanmaguitar
    CollaboratorAuthor

    Still open; the ref-fetch plumbing no longer needs implementation. fetchBranch in src/git-write.cjs fetches an explicit ref through the pinned HTTPS, HTTP, or file transports. Reframe the remaining work as UI and product state above that primitive: create the local PR branch, park and switch safely, state the dependency rebuild cost before the action, and provide the route back.

  5. juanmaguitar commented on Sep 11, 2026

    @juanmaguitar
    CollaboratorAuthor

    Spike run against the question this issue leaves implicit: once you stand on the author's branch, does it still install and build? Eight open core PRs, the real command-line ritual, on the app's own partial clone.

    The ritual is two git commands. gh pr checkout 4535 fetches refs/pull/4535/head from origin, names the local branch with the author's own head ref (58442-add-parameter-to-filter-archives, not pr/4535), and adds no remote. It only writes the fork's URL into branch.<name>.pushremote. So the app needs fetchBranch(dir, 'origin', 'refs/pull/N/head') unchanged plus a checkout. No second remote, no credentials, no new plumbing.

    Measurements (macOS arm64, Node 24.18, which is what Electron 43 ships, so this is the app's own runtime):

    head npm ci npm run build:dev
    2023-12-22 ok 13s ok
    2023-06-02 ok 15s ok 14s
    2023-02-17 ok 15s ok 15s
    2022-11-10 ok 84s
    2022-04-05 ok 17s
    2021-06-08 fails 15s
    2021-06-04 fails 24s
    2019-07-09 fails 12s

    Three corrections to the body:

    The price is seconds, not minutes. The body justifies the price-before-the-click rule with "install and rebuild, minutes not seconds". Measured: 15s + 16s. The rule loses most of its weight.

    Old branches do not take longer, they fail, on dead native dependencies (puppeteer with no arm64 Chromium, node-sass wanting a node-gyp toolchain that is gone). And they fail in 12 to 24 seconds, faster than the slowest success.

    npm install breaks the "nothing is applied" promise; npm ci keeps it. npm install rewrites package-lock.json from lockfileVersion 1 to 3, 29,100 lines inserted, and the tree is dirty before the contributor touches anything. npm ci leaves git status empty after install and after build. The app currently runs npm install (src/install-runner.js:27), so the PR route needs npm ci.

    How rare the failing case is. Of the 100 most recently updated open PRs, 97 have a 2026 head and none is older than 2022. Of the 100 oldest, 94 have a head before 2022. The dead zone is roughly 250 abandoned PRs out of 3,450 open, about 7%, all in one corner. A live core PR carries a 2026 head regardless of when it was opened.

    Two things that do not work as gates, both tested rather than assumed:

    • PR creation date. #3801 was created 2022-12-24, its head is 2023-12-22, and it installs in 13s. Only the head commit date means anything.
    • Reading the lockfile for known-dead packages. PRs that install fine carry node-sass and old puppeteer entries too. No cheap predictor.

    What this suggests for the design. No pre-emptive dialog. This issue's own test in #350 says a dialog, decision or wait added to the newcomer's path is the wrong answer, and a confirmation before crossing is exactly that, asked about a case they will almost never meet and cannot answer anyway. Instead: cross without asking; when npm ci fails, say which package died, within 20 seconds; and offer the diff route there, which for an abandoned PR works fine and already exists. The install failure becomes a first-class state rather than a wall of npm output.

    Caveats: eight PRs, one platform. The failures are puppeteer with no arm64 Chromium, so the same branches may well install on Windows x64. That is the reason not to hard-code a date threshold anywhere.

  6. added 2 commits that reference this issue on Sep 14, 2026
    c8b2cf0
    8b1341e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: patch-flowPatches, pull requests, Trac ticketsenhancementNew feature or requestreal-world-gitCloser-to-real-Git experience: the interoperability contract (#350) and its pieces

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions