dbt-refmerge
Finds duplicated import CTEs in your dbt models — two CTEs reading different
columns from the same {{ ref(...) }} — proves the merged version returns
identical rows on your warehouse, and rewrites the file. Anything it can't
prove, it leaves alone.
Use it
pip install dbt-refmerge
cd your-dbt-project
dbt-refmerge scan
That's it. The dialect is detected automatically from your
profiles.yml/manifest.json (override with --adapter postgres if
needed). You'll get one line per opportunity:
models/marts/orders.sql: order_items, order_items_summary -> ?
Each line is a lead: two CTEs over the same upstream model that may merge into one. Then, on a branch:
git checkout -b refmerge-cleanup
export DBT_REFMERGE_SCRATCH_SCHEMA=refmerge_scratch # where verification views go
dbt-refmerge check # proves each merge on your warehouse
dbt-refmerge fix models/marts/orders.sql --dry-run # preview the rewrite
dbt-refmerge fix models/marts/orders.sql # re-proves, then applies it
git diff # review, test, open a PR
scan and check never touch your files. fix refuses to write unless the
proof passes on current data (applied=false plus a reason means it's
working, not broken).
To prove a merge, check builds the original and the merged model as two
views in the scratch schema (dbt creates it if needed; it must not be a schema
your models build into), compares their column types and their rows as
multisets in a single query, then drops both views. If a run is interrupted,
dbt-refmerge cleanup --run-id <id> drops whatever it left (the id is in
check --json). Verification supports PostgreSQL in v0.1; scan parses 16
dialects (snowflake, bigquery, duckdb, databricks, redshift, trino, spark,
sqlite, tsql, oracle, exasol, clickhouse, and more).
Develop it
Keep the inner test loop focused and in memory:
pip install -e ".[dev,integration]"
python3 -m pytest -q tests/unit/test_odd_scenarios.py # odd-scenario safety lane
python3 -m pytest -q # unit lane (default)
python3 -m ruff check .
python3 -m mypy --strict src
The default run is the in-memory unit lane and takes a few seconds on a typical development machine. Two slower lanes are opt-in:
python3 -m pytest -q -m fake_dbt # subprocess tests against tests/fakes/fake_dbt.py
docker run --rm -d --name refmerge-pg -p 5432:5432 \
-e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=refmerge postgres:16
export REFMERGE_TEST_PG_DSN=postgresql://postgres:postgres@localhost:5432/refmerge
python3 -m pytest -q -m warehouse # needs Postgres and dbt-postgres
python3 -m pytest -q -m "" --cov # every lane; enforces the coverage floor
TEST_COVERAGE_PLAN.md tracks the path to 100% coverage.
Support
If this saves you an afternoon, buy me a coffee.
MIT license. Requires Python ≥ 3.11 and your own dbt installation.
Release files for dbt-refmerge 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dbt_refmerge-0.1.0.tar.gz | 133.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dbt_refmerge-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 206.5 kB
Release files / dbt_refmerge-0.1.0.tar.gz
| Download URL | dbt_refmerge-0.1.0.tar.gz |
|---|---|
| Size | 133.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
db8e528149814c4cea89346513597a3c4685dc0e8a828ce62a2c31191347a45b
|
|
BLAKE2b-256 checksum How to use checksums |
3b2569912b13d9a8d967d2b8c8ab2fa515d4b0527d27cbe1aac3707034ac39b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency logRelease files / dbt_refmerge-0.1.0-py3-none-any.whl
| Download URL | dbt_refmerge-0.1.0-py3-none-any.whl |
|---|---|
| Size | 73.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6949ab831a5313ce72215a2e6a1eb2726d769419be66ebb170cdc6401941b3c5
|
|
BLAKE2b-256 checksum How to use checksums |
3784d01b5949957a35aac58319a77a8ae3a6e3811969228325721d438f0dd4b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency log