Skip to content
Writing
Operations5 min read

Push-to-deploy without the accidents

Connecting git to your host means a stray push reaches customers. Here's the gate we put in front of the site that takes payments.

Push-to-deploy is the right default for most projects. Commit, push, and the change is live — no CLI ceremony, and every branch gets a preview URL you can hand to a client.

It's the wrong default for exactly one kind of project: the one that moves money. When a client billing portal deploys on every push to the main branch, there is nothing between a distracted afternoon and a production incident with real invoices attached.

The gate is a second branch

Rather than disconnecting git entirely and losing preview builds, point the production environment at a dedicated branch. Day-to-day work pushes to main and produces a preview; shipping is an explicit, differently-shaped command.

git push origin main               # preview URL only — safe
git push origin main:production    # deploys production — deliberate

The protection isn't cryptographic. Nothing stops you pushing to the production branch. What it buys is that the dangerous action no longer shares a command with the safe one, so it can't happen by muscle memory.

Verify the gate, don't assume it

We nearly learned this the wrong way. During the same audit we pushed some catch-up commits to another project, not realizing it was already connected to its host — and that push deployed production without anyone intending it. It built cleanly and no harm came of it, but the lesson stands: check whether a repository is already wired to deploy before you push to it, not after.

After changing any deploy configuration, prove it with a real push and watch which environment the build lands in. A settings page that claims a gate exists is not the same as a gate that has been observed working.

Where teams get this wrong

  • Assuming branch protection is available. On several hosting plans it simply isn't offered for private repositories, and the feature fails silently until you try to configure it.
  • Treating a green deploy as evidence that safeguards work. It's evidence the deploy path works, nothing more.
  • Leaving the manual override in place without documenting it. A direct CLI deploy still bypasses every branch gate you built.

The goal isn't to make production unreachable. It's to make reaching production a decision rather than a reflex.

We build this kind of thing for a living.

Start a conversation