## TL;DR
Two revision chains grew from the same parent, so alembic cannot pick one upgrade path. List the heads, create a merge revision that depends on both, and upgrade through it. The merge revision usually has empty upgrade and downgrade bodies; its only job is to join the graph. Add a heads check to CI so the next branch collision fails fast instead of surprising a deploy.

## The query

```text
alembic error: Multiple heads are present - how to merge branching heads
```

## Use this when

- alembic upgrade head fails with "Multiple heads are present"
- Two branches each added a migration from the same parent
- alembic heads lists more than one revision
- An agent merged branches without noticing the migration graph forked

## Not for

- "Can't locate revision" (a deleted file, not a fork)
- A single head that is simply behind (run upgrade head)
- Intentionally branched histories you plan to keep separate (rare; document it explicitly)

## Steps

### 1. List the heads and see the fork

```bash
alembic heads
```

Expected output: two or more revision ids. Follow with alembic history to see which parent they share and what each branch contains.

### 2. Check both branches apply cleanly on their own

On a scratch database, upgrade to each head in turn (downgrade between runs) and confirm neither branch is broken independently. A merge cannot fix a branch that was already failing.

Expected output: both heads apply without errors on a fresh database. If one fails, fix that branch first.

### 3. Create the merge revision

```bash
alembic merge -m "merge heads" [head-a] [head-b]
```

Expected output: a new revision file whose down_revision is the tuple of both heads, with empty upgrade and downgrade functions. Review the file: it should contain no schema operations, only the join.

### 4. Upgrade through the merge on a scratch database first

```bash
alembic upgrade head
```

Expected output: alembic applies whichever branch is missing and then the merge revision, ending on the new single head. Verify the final schema matches what both branches intended.

### 5. Add a single-head gate to CI

Add a step that fails the build when alembic heads returns more than one line. Branch collisions then surface at pull-request time, where the merge is cheap, instead of at deploy time.

Expected output: future forks break the build with a clear message instead of breaking the deploy with "Multiple heads are present".

## Tool compatibility

alembic 1.x, all backends. alembic merge has existed with the same behavior since 0.7.

## Variant phrasings

### alembic merge branching heads

Step 3 is the whole fix: alembic merge with both head ids.

### alembic two heads after branch merge

Steps 1 and 3: confirm the fork, then merge. The git merge is fine; only the revision graph needs the join.

### Multiple heads are present alembic how to fix

Steps 3 and 4: create the merge revision and prove it upgrades cleanly on a scratch database before touching shared environments.

## Why it happens

Alembic models history as a directed graph and upgrade head means "walk from the current version to the single head". When two revisions share a parent, the graph has two heads and no unique path, so alembic stops instead of guessing. A merge revision is an explicit statement that both branches are wanted.

## Edge cases

- If the two branches touch the same table incompatibly (one drops a column the other alters), the merge upgrades in an arbitrary order: review both branches' operations for conflicts, not just the graph.
- A merge revision with real DDL in it is a smell: keep merges empty and put schema work in normal revisions.
- If one head was a mistake that never applied anywhere, deleting its file is cleaner than merging it in. Only merge branches you intend to keep.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_eShozh7OiVVJk37PlbTaHw
