---
modified: '2026-09-16'
title: Merge Path & Production Releases
---

_Last updated: {{< meta modified >}}_

## The rule

`main` is production. `dev` is integration.

> **Pull requests into `main` may only come from this repository's `dev` branch.**

Every other route to `main` is blocked:

- Direct pushes to `main` are rejected. Force-pushes and deletion are blocked permanently.
- A pull request from any other branch (`feature/*`, `fix/*`, `hotfix/*`, `codex/*`, ...) fails the
  required `merge-path-guard` status check and cannot be merged.

## Normal flow

```
<type>/<name>   ->   dev   ->   main
```

1. Branch from `dev` and open your pull request against `dev`.
2. Once it is merged into `dev`, open a pull request from `dev` into `main` and merge it.

The `dev -> main` step needs no approval: `main` is a promotion gate, not a second review.

## If the guard blocked you

The `merge-path-guard` workflow comments on your pull request explaining the path. Read that
comment. In particular, do not:

- retarget the base branch of a pull request that already passed the check — the check re-runs
  (`edited` is among its triggers),
- rename your branch to `dev`,
- try to push directly to `main`.

All three fail.

## Emergency hotfix

If production must be fixed without waiting for `dev`:

1. Open the pull request from your `hotfix/*` branch **into `main`**. It will fail
   `merge-path-guard`. That failure is expected and is not an error.
2. Ask the maintainer (`@kantundpeterpan`) to merge it with the repository-admin override.

The override is scoped to pull requests only: nobody, including the maintainer, can push directly
to `main`. Bypassed merges are recorded in the pull request banner and the repository audit log.

## Configuration reference

| Concern | Where |
|---|---|
| The check | `.github/workflows/merge-path-guard.yaml` — job `merge-path-guard` |
| Required status check | repository ruleset `main-merge-path` |
| Force-push / deletion block | repository ruleset `main-integrity` (no bypass) |
| Ownership of the check | `.github/CODEOWNERS` |
