Skip to content

Merge Desk

AI merges that wait for proof.

Gemini proposes how to resolve a pull request's merge conflict. Nothing lands until the result parses, keeps what each side chose to keep, and passes the repository's real tests.

Try the demo No account, and it writes nothing.

[Demo] Rename fetchUser to getUser #1

oursdemo/clean/renameintotheirsdemo/base

ours
renamed fetchUser to getUser and added a deprecated alias
theirs
added retry logic on HTTP 429 to fetchUser

Combine bothRecommendedby Gemini (gemini-3.5-flash-lite)

  1. Revisions unchangedpassed544 ms

    head df6c107 · base a41f224

  2. Propose mergepassed1.4 s

    Gemini (gemini-3.5-flash-lite): combines the getUser rename with the 429 retry logic

  3. Write on scratch copypassed5.3 s

    6 files differ from the head: playground/src/api.js, playground/src/billing.js, playground/src/money.js, playground/test/billing.test.js, playground/test/money-rounding.test.js, playground/test/retry.test.js

  4. It parsespassed136 ms

    playground/src/api.js: node --check

  5. Choice honoredpassed11 ms

    ours: renamed fetchUser to getUser and added a deprecated alias, present theirs: added retry logic on HTTP 429 to fetchUser, present

  6. Testspassed2.9 s

    node --test (playground): passed (exit 0, 451 ms)

VERIFIEDLanded on demo/clean/rename as 393147f
A real run, recorded October 7, 2026: Gemini proposed the merge and a Vercel Sandbox merged it and ran the tests. Played back at its original pace.

Pick a resolution. The gate answers.

The same conflict, each option Gemini offered, each run for real. Choose one to see what the checks recorded.

Resolution for pull request #1

Run these yourself in the demo

Proposed, checked, landed.

ours
renamed fetchUser to getUser and added a deprecated alias
theirs
added retry logic on HTTP 429 to fetchUser
  • Combine bothRecommended
  • Keep ours, drop theirs
  • Keep theirs, drop ours

Proposed

Gemini reads both branches, states what each side meant in one sentence, and offers ways to resolve the conflict, each naming what it keeps and what it drops.

Keep ours, drop theirs, steered: Keep the old call working too.

  • It parsespassed

    playground/src/api.js: node --check

  • Choice honoredfailed

    ours: renamed fetchUser to getUser and added a deprecated alias, MISSING (1 line)

    theirs: added retry logic on HTTP 429 to fetchUser, LEAKED into the result (6 lines) although it was dropped

    playground/src/api.js: 1 line both sides kept are missing

  • Testspassed

    node --test (playground): passed (exit 0, 422 ms)

HELD

Checked

In a fresh sandbox with its network off, the merge has to parse, keep exactly what the chosen option says, and pass the real tests. This retry passed the tests and was still held: it brought back the retry its option had dropped.

LANDEDin 6.8 s
Head
df6c107 unchanged since the run
Base
a41f224 unchanged since the run
Commit
393147f added to demo/clean/rename
Record
landed by YearningAsian, Combine both
  • Revisions unchanged
  • Propose merge
  • Write on scratch copy
  • It parses
  • Choice honored
  • Tests

Why: This is the best choice because it preserves both the architectural rename and the new bugfix/feature without losing code.

Landed

Land rechecks that neither branch moved, then adds the merge commit to the pull request's own branch. Never its base, never main, never a force push. Every decision goes into one comment on the pull request.

Why merges need a gate

Conflicts take reasoning, and conflicted code breaks more often. So the model only proposes.

143

open source projects in the merge conflict study

75.23%

of their conflicts needed reasoning about program logic

2x

as likely to have a bug, for code tied to a conflict

15

real runs recorded for the demo, Gemini and sandbox included

12

of those runs HELD, each with its reason

3

real Lands on demo pull requests, each reset afterwards

Study: Brindescu, Ahmed, Jensen and Sarma, Empirical Software Engineering, 2019. Our runs: every number comes from the recordings and is served with the command that measured it at /api/stats.

Open a conflict.

The demo replays the real runs on three pull requests, at their original pace. No account, and nothing is written to GitHub.