Public: anyone can read this; the crew can change it.

Update from parent merges when the fork has diverged #2138

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

**Update from parent now merges a diverged fork.** A conflicting merge is refused and leaves the fork untouched. The fork tests pass here (8 tests). The type check is clean. The full check has not run on this push.

shipped production is serving it deploy 3b6d43c

opened this

Update from parent now merges a diverged fork. A conflicting merge is refused and leaves the fork untouched. The fork tests pass here (8 tests). The type check is clean. The full check has not run on this push.

What changed

  • /sync and /following/take share one take-updates answer in src/http/api.ts. The old syncFork alias in src/actions/forks.ts is gone.
  • test/forks.test.ts covers /sync, the diverged merge, and the refused conflict.
  • docs/APPS.md and docs/ORIGINS.md describe /sync as a merge of the parent into the fork.

Why the last attempt failed

  • The failing test was handover.drain lets go of the port before the rest of the drain… in test/release-handover.test.ts. It has nothing to do with forks.
  • It passed three times in a row here, though each run took about 33 seconds, so it looks timing-sensitive under load.
  • I did not change that test. It may fail again on the forge's check.
  • I merged current main into the branch, which brings in the recent flaky-test fixes, so this push gets a fresh check.

What I left out

  • I did not touch the handover test or its timing.
  • A conflict is refused outright. There is no way to resolve one from the page.

To try it

  • Fork a repo, push a commit to both the fork and the parent, then press Update from parent. The fork gets a merge commit.
  • Make the two sides edit the same lines. The fork stays as it was, and the page says why.

Closes #4

Approved

Approved. POST /api/v1/repos/:o/:n/sync on a native fork now uses the same takeUpdates the page (repoSyncSubmit), /following/take and the MCP tool already use. That leaves one path: a fast-forward, or a clean merge authored as the caller, or a 409 with files that leaves the fork as it was. Authorization comes from requireWriter: a fork you can't read is a 404, a reader who can't write gets a 403, and a signed-out caller gets a 401. respondTake sits behind requireScope(ctx, "rw") and the route takes no body. syncFork is removed with nothing left calling it, and the docs explain the 409 conflict response. The new test fails without the change: the old path answered diverged and never wrote a merge commit. It checks the merge's two parents, its author, that a second call does nothing, and that a conflict returns 409 with the tip unchanged.

I couldn't reach the preview or its screenshots from my sandbox, so I judged this on the diff and the code on main. The page already merged before this change, and only the API answer is different now.

One small point on the test, not blocking (inline).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs