# The Deploy That Quietly Undid Someone Else's Work
I want to start with the part that still bugs me: nothing broke loudly. No red build, no failing test, no alert. Two edge functions simply stopped doing things they had been doing a little earlier, and the tooling was perfectly happy about it.
So this is a write-up of that. Short version: a deploy from an unmerged branch overwrote live code, other people's changes vanished, and it took about 25 minutes to put them back. The details are more interesting than the summary, though, and the lesson travels well beyond us.
Symptom
The repository is scriptgrain, and the work in flight was the long-drafts release. On 2026-09-27, the live api-v1 and generate-content edge functions were deployed from the feature branch. That was before the branch had been merged.
What we saw afterwards was behaviour that had already shipped, from another session working on the same repo, no longer being there. Changes that were live and working were gone from both functions. They stayed gone for 25 minutes (that's the measured figure, minutes_overwritten: 25), until the functions were redeployed from the merged main tree.
That's it. No error message to quote, because there wasn't one. The functions ran fine. They just ran the wrong version of themselves.
What we thought it was
The first diagnosis was a regression in the long-drafts work itself. Obviously, right? We'd just touched these functions, the release was new, and something that used to work had stopped working. The most believable explanation is always "the thing we just built has a bug."
It was believable for a good reason: it's usually true. New code breaks old behaviour all the time, and when you've just shipped a feature the instinct to go and read your own diff is a sound one. So that's where the looking started.
But the diff was fine. The long-drafts changes did what they were meant to do. What was missing wasn't something the feature branch had broken; it was something the feature branch never contained in the first place. That's a different kind of problem, and a diff of your own work will never show you an absence of someone else's.
I'll admit that took longer to see than it should have. When the evidence says "this code is wrong" and the truth is "this code is incomplete," you can stare at the first for a while.
Root cause
Here's what's actually going on, and it's almost boring. A deploy ships whatever is in the local tree, and it overwrites whatever is live. That's all it does. It doesn't merge. It doesn't compare. It doesn't ask what's currently running.
So when the feature branch went out to api-v1 and generate-content, it replaced the live copies wholesale with the branch's version. The branch didn't have the other session's already-live changes, because those had been made elsewhere and hadn't been merged in. Overwritten, cleanly, no conflict.
And here's the nasty bit. There's no deploy history that shows whose code is running. You can't open a log and see "this version came from that branch, by that session." The live function is just a function. Whatever got deployed last is what exists, and nothing records the lineage. Git knows about commits; the deploy target knows about the latest upload. Those two things don't talk to each other.
The commit that restored things was 1c291d2, redeployed from the merged main tree. That's where the missing changes finally lived alongside the long-drafts work, which is the only reason redeploying from there fixed it.
The fix
The immediate fix was a redeploy. Both functions, from the merged main tree, on 2026-09-27. Once main contained everything (the long-drafts work and the other session's changes together), shipping main put both sets of behaviour back live at once.
Nothing clever. No patch, no rewrite. The code we needed already existed in the right place; it just hadn't been the thing that got deployed. The fix was making the deployed version and the merged version the same thing again.
Then came the rule, which is the part that actually changes anything going forward: when other sessions are active on a repo, merge first, and deploy only from a clean export of origin/main. And if you need to test unmerged code, deploy it under a new function name. Never a shared one.
Why it happened
This is the section I care about most, because "someone deployed the wrong thing" is a symptom, not a cause.
The systemic problem is that the deploy path and the review path are separate. Review looks at a diff against a branch. It checks whether the change is good. It does not check whether the thing being deployed is the thing that's already running, because review has no idea what's running. So everything can be approved, correctly, and the deploy still removes someone's work.
Nobody did anything outrageous. Deploying from a feature branch to check it against the real environment is a reasonable thing to want. The environment just doesn't tell you that a shared function is shared. It looks identical to a function that's yours alone.
That's how it survived. Each step was individually sensible, and the dangerous bit lived in the gap between steps, where no tool was looking.
How to avoid it
If you're reading this and you're not us, the transferable part is simple. Treat a deploy as a write to shared state, because it is one. It has no merge semantics, so you have to supply them yourself, beforehand.
Merge first. Always. If other people or other sessions are touching the same repo, the only version that's safe to ship is one that already contains everyone's work, and that's what origin/main is for. Deploy from a clean export of it, not from whatever happens to be sitting in your working tree.
For testing unmerged code, give it its own name. A new function name costs you nothing and can't overwrite anyone. A shared name can wipe out work you never knew existed, silently, and you won't find out until something that used to work doesn't.
And don't trust the absence of an error. Ours came with none. Anyway, that's the whole story: 25 minutes, one overwrite, and a rule that now lives where the deploys happen.
Every commit, file reference and date above is checked
against this incident's Noctem evidence pack before publication. Evidence:
branch-deploy-overwrote-live-api-v1-edge-function.