dbdiff/dbdiff

Maintainers

Package info

github.com/DBDiff/DBDiff

Type:project

pkg:composer/dbdiff/dbdiff

Statistics

Installs: 118 662

Dependents: 0

Suggesters: 0

Stars: 730

Open Issues: 87


README

DBDiff logo

Build Status Total Downloads Monthly Downloads License

DBDiff is an automated database schema and data diff tool. It compares two databases, local or remote, and produces a migration file of the differences automatically.

When used alongside a compatible database migration tool, it can help enable database version control within your team or enterprise.

Features

  • Compares two databases (local or remote) and generates SQL migrations automatically
  • Diffs schema changes, data changes, or both — with deterministic, predictable output
  • Up and down SQL generated in the same file
  • Supports MySQL, PostgreSQL, and SQLite via --driver
  • Supabase-ready via --supabase one-flag shorthand
  • Works with Flyway, Liquibase, Laravel Migrations, and more
  • Ignore specific tables or fields via a YAML config file
  • Unicode / UTF-8 aware
  • Fast — tested on databases with millions of rows
  • Runs on Windows, Linux and macOS (command-line / Terminal)

Supported Databases

Other versions may work but are not actively tested. PRs to add official support are welcome.

MySQL

Version Status
MySQL 8.0.x ✅ Supported
MySQL 8.4.x (LTS) ✅ Supported
MySQL 9.3.x (Innovation) ✅ Supported
MySQL 9.6.x (Innovation) ✅ Supported

PostgreSQL

Use --driver=pgsql (or driver: pgsql in your .dbdiff config).

Version Status
PostgreSQL 14.x ✅ Supported
PostgreSQL 15.x ✅ Supported
PostgreSQL 16.x (LTS) ✅ Supported
PostgreSQL 17.x ✅ Supported
PostgreSQL 18.x ✅ Supported

SQLite

Use --driver=sqlite. The file path is passed as the database name:

./dbdiff --driver=sqlite server1./path/to/source.db:server1./path/to/target.db

SQLite 3.x is supported (any version supported by the installed pdo_sqlite PHP extension).

Supabase

--supabase sets driver=pgsql and enables SSL automatically:

./dbdiff --supabase --server1=user:pass@db.xxx.supabase.co:5432 server1.mydb:server1.mydb

Compatible Database Variants

The databases below work with DBDiff's existing drivers with no code changes. Unless otherwise noted, these have not been tested by the core team. PRs to add official support are welcome.

MySQL-compatible — --driver=mysql (default)

Database Notes
MariaDB 10.x / 11.x MySQL wire protocol; minor DDL dialect differences
AWS Aurora MySQL Standard MySQL protocol
PlanetScale MySQL-compatible SaaS
Vitess / VTGate MySQL wire protocol via VTGate
Percona XtraDB Cluster MySQL-compatible; Galera replication metadata ignored
TiDB MySQL-compatible; default port 4000

PostgreSQL-compatible — --driver=pgsql

Database Notes
AWS Aurora PostgreSQL Standard pgsql connection
AWS RDS PostgreSQL Standard pgsql connection
Neon Standard pgsql; supports branch diffing (see below)
AlloyDB (Google Cloud) Google's Postgres-compatible offering
CockroachDB Postgres wire protocol; some DDL differences
YugabyteDB Postgres-compatible YSQL layer
Multigres Transparent Postgres proxy; no changes needed
TimescaleDB Postgres extension; hypertable DDL diffs natively
pgvector vector(N) columns and HNSW/IVFFlat indexes diff natively

Neon Branching

Neon's copy-on-write branching lets you diff any two branches directly:

./dbdiff \
  --server1-url postgres://user:pass@main-branch.hostname.neon.tech/mydb \
  --server2-url postgres://user:pass@feature-branch.hostname.neon.tech/mydb \
  --format=flyway --description=my_feature

Dolt (Git for Databases)

Dolt is a MySQL-compatible database with Git-style branching. Each branch is exposed as a separate database:

./dbdiff server1.main:server1.feature_add_users

Installation

The quickest way to get started is to download a pre-built release directly from GitHub Releases — no PHP, Node, or Composer required:

Method Available on Releases? Best for
Pre-built binary ✅ Yes Quickest start — zero dependencies
PHAR ✅ Yes Single portable file; requires PHP ≥ 8.1
npm ✅ Yes (via registry) Node.js projects or CI pipelines
Docker Isolated environments or testing
Composer (source) Contributing to DBDiff or PHP integration

PHP requirement: Pre-built binaries, npm packages, and Docker images bundle PHP 8.3 — no system PHP needed. The PHAR and Composer installs require PHP ≥ 8.1 on your system.

Pre-built Binaries

Download from GitHub Releases. No PHP, Node, or Composer required.

Platform Asset
Linux x64 (glibc) dbdiff-linux-x64
Linux x64 (Alpine / musl) dbdiff-linux-x64-musl
Linux arm64 (glibc) dbdiff-linux-arm64
Linux arm64 (Alpine / musl) dbdiff-linux-arm64-musl
macOS Apple Silicon dbdiff-darwin-arm64
macOS Intel dbdiff-darwin-x64
Windows x64 dbdiff-win32-x64.exe
Windows arm64 dbdiff-win32-arm64.exe

After downloading, make it executable (Linux/macOS) and optionally move it to your PATH:

chmod +x dbdiff-linux-x64
sudo mv dbdiff-linux-x64 /usr/local/bin/dbdiff
dbdiff --version

npm

npm install -g @dbdiff/cli
dbdiff --version

The correct platform binary is selected automatically at install time. Supported: Linux x64/arm64 (glibc + musl), macOS x64/arm64, Windows x64/arm64.

PHAR

Download dbdiff.phar from GitHub Releases. Requires PHP ≥ 8.1.

chmod +x dbdiff.phar
sudo mv dbdiff.phar /usr/local/bin/dbdiff
dbdiff --version

To build a PHAR locally from source, see Building a PHAR.

Docker

Pre-built multi-arch images (linux/amd64 + linux/arm64) are published to GHCR on every release.

Pull and run (no build required)

docker pull ghcr.io/dbdiff/dbdiff
docker run --rm ghcr.io/dbdiff/dbdiff --version
docker run --rm ghcr.io/dbdiff/dbdiff --driver=mysql \
  --server1=user:pass@host:3306 server1.mydb:server1.mydb

Image variants

Tag pattern Registry Description
latest, {version}, slim-{version} GHCR Slim — PHAR + PHP Alpine (~120 MB). For production use / CI.
full, full-{version} GHCR Full — Composer source install (~600 MB). For development and cross-version testing.

Build locally

# Slim image (requires dist/dbdiff.phar — run `vendor/bin/box compile` first)
docker build -f docker/Dockerfile.slim -t dbdiff:slim .
docker run --rm dbdiff:slim --version

# Full image (Composer install from source — no PHAR needed)
docker build -f docker/Dockerfile -t dbdiff:full .

See DOCKER.md for cross-version testing, Podman usage, and start.sh flags.

Composer Source Install

git clone https://github.com/DBDiff/DBDiff.git
cd DBDiff
composer install --optimize-autoloader

Or as a project dependency:

composer require "dbdiff/dbdiff:@dev"

Or globally:

composer global require "dbdiff/dbdiff:@dev"

After installing from source, continue with Setup.

Setup

For source installs (git clone / Composer) only. Binaries, PHAR, npm, and Docker do not require these steps.

  1. Create a .dbdiff config file — see File Examples
  2. Run: ./dbdiff server1.db1:server1.db2

Expected output:

ℹ Now calculating schema diff for table `foo`
ℹ Now generating UP migration
ℹ Writing migration file to /path/to/dbdiff/migration.sql
✔ Completed

Command-Line API

Flags always override settings in .dbdiff.

Flag Description
--server1=user:pass@host:port Source connection. Omit if using only one server.
--server2=user:pass@host:port Target connection (if different from server1).
--driver=mysql|pgsql|sqlite Database driver. Defaults to mysql.
--supabase Shorthand for --driver=pgsql + SSL.
--format=native|flyway|liquibase-xml|liquibase-yaml|laravel Output format. Defaults to native.
--description=<slug> Slug used in generated filenames.
--template=<path> Custom output template.
--type=schema|data|all What to diff. Defaults to schema.
--include=up|down|all Directions to include. Defaults to up.
--nocomments=true Strip comment headers from output.
--config=<file> Config file path. Defaults to .dbdiff.
--output=<path> Output file path. Defaults to migration.sql.
server1.db1:server2.db2 Databases to compare. Or a single table: server1.db1.table1:server2.db2.table1.

Usage Examples

MySQL (default)

./dbdiff server1.db1:server2.db2

MySQL — data diff only

./dbdiff server1.dev.table1:server2.prod.table1 --nocomments=true --type=data

MySQL — Flyway format with output path

./dbdiff --format=flyway --description=add_users --include=all \
  server1.db1:server2.db2 --output=./sql/

PostgreSQL

./dbdiff --driver=pgsql --server1=user:pass@localhost:5432 server1.staging:server1.production

Supabase

./dbdiff --supabase --server1=postgres:pass@db.xxxx.supabase.co:5432 \
  server1.staging:server1.production

SQLite

./dbdiff --driver=sqlite server1./var/db/v1.db:server1./var/db/v2.db

File Examples

A single dbdiff.yml file in your project root configures both the diff command and the migration runner. Copy dbdiff.yml.example to get started.

Auto-detected filenames, in priority order:

Filename Notes
.dbdiff Legacy — still supported for backwards compatibility
dbdiff.yml Recommended — YAML syntax highlighting, single file for everything
.dbdiff.yml Hidden-file variant
dbdiff.yaml .yaml extension variant

You can also pass any filename explicitly: ./dbdiff --config=myconfig.yml server1.db:server2.db

dbdiff.yml

# ── Diff command (./dbdiff server1.db:server2.db) ─────────────────────────
server1:
  user: user
  password: password
  port: 3306      # MySQL: 3306 | PostgreSQL: 5432
  host: localhost
server2:
  user: user
  password: password
  port: 3306
  host: host2
driver: mysql     # mysql | pgsql | sqlite
type: all
include: all
nocomments: true
tablesToIgnore:
  - table1
  - table2
fieldsToIgnore:
  table1:
    - field1
    - field2

# ── Migration runner (dbdiff migrate:up) ──────────────────────────────────
database:
  driver: mysql
  host: localhost
  port: 3306
  name: mydb
  user: root
  password: secret

migrations:
  dir: ./migrations
  history_table: _dbdiff_migrations

How Does the Diff Work?

Comparisons run in this order:

Overall

  • Checks both databases exist and are accessible
  • Compares database collation between source and target

Schema

  • Detects differences in column count, name, type, collation or attributes
  • New columns in the source are added to the target

Data

  • Compares table storage engine, collation, and row count
  • Records changed rows and missing rows per table

Compatible Migration Tools

DBDiff supports multiple output formats via --format. Use --description=<slug> to customise generated filenames.

--format Tool Language Output Notes
native (default) Plain SQL Any migration.sql Up, down, or both
flyway Flyway Java V{ts}__{desc}.sql Down adds U{ts}__{desc}.sql (Flyway Teams)
liquibase-xml Liquibase Java changelog.xml Both directions in one file
liquibase-yaml Liquibase Java changelog.yaml Both directions in one file
laravel Laravel Migrations PHP YYYY_MM_DD_HHMMSS_{desc}.php up()/down() methods
(template) Simple DB Migrate Python custom Use --template=templates/simple-db-migrate.tmpl

Let us know if you're using DBDiff with other tools so we can add them here.

Building a PHAR

PHARs are built automatically and attached to every GitHub Release. To build locally from source:

composer install
vendor/bin/box compile

Output: dist/dbdiff.phar — rename and move to /usr/local/bin/dbdiff if desired.

box.json is pre-configured with GZ compression and check-requirements: false so the PHAR works correctly when stitched with the static micro SAPI runtime used in the pre-built binaries.

Releasing 🚀

Automated (recommended)

  1. Go to GitHub Actions → Release DBDiff → Run workflow
  2. Enter the version number (e.g. 2.1.0 — no v prefix)
  3. The workflow will:
    • Build the PHAR with Box
    • Build self-contained binaries for all 8 platforms via static-php-cli
    • Publish all @dbdiff/cli-* packages to npm (skips any already published)
    • Create or update the GitHub Release with all assets
    • Create the git tag (skipped if it already exists)

Manual / local

# Build PHAR + tag
scripts/release.sh v2.1.0
git push origin v2.1.0

# Build Linux binaries locally (requires Podman or Docker)
SKIP_PHAR=1 scripts/release-binaries.sh 2.1.0

# Upload assets to an existing GitHub Release
gh release upload v2.1.0 --clobber \
  dist/dbdiff.phar \
  packages/@dbdiff/cli-linux-x64/dbdiff \
  packages/@dbdiff/cli-linux-x64-musl/dbdiff \
  packages/@dbdiff/cli-linux-arm64/dbdiff \
  packages/@dbdiff/cli-linux-arm64-musl/dbdiff

# Update the Homebrew tap formula
scripts/update-homebrew-formula.sh 2.1.0 ../homebrew-dbdiff

Cross-Version Testing

Test DBDiff locally against any combination of PHP and MySQL:

# Single combination
./start.sh 8.3 8.0

# All 16 combinations in parallel
./start.sh all all --parallel

The CI matrix: 6 PHP × 4 MySQL = 24 jobs, plus dedicated jobs for SQLite and PostgreSQL.

See DOCKER.md for flags covering fast restarts, recording fixtures, and CI usage.

Questions & Support 💡

Contributions 💖

Please read the Contributing Guide before submitting a PR.

Feedback 💬

Could you spare 2 minutes to share your feedback?

https://forms.gle/gjdJxZxdVsz7BRxg7

License

MIT

Made with 💖 by
Akal Logo