All demos/ Pull and sync

DEMO-03-SYNCSEP 2026

Retrofit stops the app before it runs against the wrong schema.

A teammate adds a column to the operation log and pushes. We pull. Before the app runs, one Makefile check finds the local database behind the log, and make db-sync renders the migration from the database’s own dump.

Stack
make + git + PostgreSQL
Change
AddColumn by pull, drift by hand
Reverse
none; the gate is read-only

Summary

You pull teammates’ code and schema changes every day, and the local database is the one thing the pull does not update.

git pull updates the code and the operation log beside it. It cannot update the local database. So the team’s run target checks first: a schema-only pg_dump, and identify reports where in the log that schema is from. At the head, the app starts. Behind it, expect-mismatch, and the make target that fixes it.

After a git pull that carries a schema change, make run exits 2 before the app starts, reports the version the database is at and the operation the log has after it, and make db-sync migrates the database there from its own dump. No history table is consulted. pg_dump reads the database, and retrofit reads the dump.

The dump is retrofit’s only input; it never connects to a database. psql applies what migrate emits, make is the gate, and git carries the log.

Below is the team’s Makefile in full, the file the recordings run. The gate is the two lines under check-db, and db-sync is the fix.

The team's Makefile
# The team's Makefile. Two targets matter here.
#
#   make run          check the local database against the operation log,
#                     then start the app
#   make db-sync      update the local database to the head of the log
#
# check-db is the whole idea. It is an ordinary prerequisite of run, so the
# check happens on every run without anyone remembering to do it. It costs
# one schema-only dump and one Retrofit command, and it stops with
# expect-mismatch when a pull updated the log and the database is behind
# it. The fix is make db-sync.
#
# Retrofit reads the dump. pg_dump and psql are what touch the database.
# -q drops Retrofit's note tier; warnings and errors still print, and
# nothing here filters or rewords them.

DB ?= postgres://postgres@localhost:55437/shop
SCHEMA ?= shop

.PHONY: run check-db db-sync

run: check-db
	./bin/app "$(DB)"

check-db:
	pg_dump --schema-only --schema=$(SCHEMA) "$(DB)" > .db.dump.sql
	retrofit identify .db.dump.sql --expect last -q

db-sync:
	pg_dump --schema-only --schema=$(SCHEMA) "$(DB)" > .db.dump.sql
	retrofit migrate --from-dump .db.dump.sql -q | psql "$(DB)" -v ON_ERROR_STOP=1 -q

Chapter 01A git pull leaves the local database behind

How do we find out the local database is behind the log?

make run passes: the database matches the log and the app starts. A teammate added one AddColumn to the log, in the same commit as the code that reads it, and git pull brings both. make run now exits 2 with expect-mismatch before the app can fail on the missing column. The database is at v1, the log has the teammate’s operation after it, and the hint names the migrate command that renders the migration.
29 sec space to pause f for fullscreen
Read transcript

pull-and-sync-demo: pull

Generated from the demo script. Every command below is run verbatim by the recording.

1/3 before the pull

an orders service. its schema is an operation log in git, beside the code. make run checks our database against that log before it starts the app:

make run

2/3 a teammate pushes, we pull

a teammate added a column to orders, changed the app to read it, and pushed. we pull:

git pull -q && git show --stat --oneline HEAD

the schema change came with the code, as one operation in the log:

retrofit op show -q | cut -c1-72

3/3 make run stops

our database does not have that column. the app would fail on its first query, so make run checks first:

make run

exit status 2

exit 2, before the app started. identify read a schema-only dump of our database and reported where in the log it is: v1, with the teammate’s operation after it. the hint is the command that renders the migration.

  1. check-db is a prerequisite of run. It takes a schema-only dump of the database, and identify reports where in the log that schema is from. Today that is the head, so the app starts.

  2. A teammate added one AddColumn to the log, in the same commit as the code that reads it, and the pull brings both. The database on our laptop does not have it yet.

  3. The log was updated and the database was not. identify reports the database is at v1 and the updated log has the teammate’s operation after it. check-db exits 2 before the app starts, with expect-mismatch and the migrate command that renders the migration.

Chapter 02The database catches up from its own dump

How does the local database catch up with the log?

make run is still stopping. The hint names migrate --from-dump, which renders the migration script that updates the database to the current version of the log, reading where the database is from the dump rather than from a history table. One ALTER. make db-sync renders it again and pipes it to psql. The same check passes, and the app reads its new column.
27 sec space to pause f for fullscreen
Read transcript

pull-and-sync-demo: sync

Generated from the demo script. Every command below is run verbatim by the recording.

1/3 still behind

we pulled a teammate’s commit: a column added to orders, as one operation in the log, and the app changed to read it. our database does not have it, so make run stops before the app can fail:

make run

exit status 2

2/3 the migration

the hint names migrate –from-dump. it reads where our database is from the dump, not from a history table, and renders the script that updates it to the current log:

retrofit migrate --from-dump .db.dump.sql -q

one statement.

3/3 sync and run

db-sync renders the same script from the same dump and pipes it to psql:

make db-sync

the same check now passes, and the app reads its new column:

make run
  1. Nothing has changed since the pull. make run exits 2 again with expect-mismatch, and its hint names the migrate command that renders the migration.

  2. migrate renders the migration script that updates the database to the current version of the log. --from-dump reads where the database is from the dump, not from a history table. One ALTER TABLE, and nothing else.

  3. make db-sync renders the same script from the same dump and pipes it to psql. make run passes, and the app reads its new column.

Chapter 03Run it end to end

Start with make run passing, pull a teammate’s AddColumn with the code that reads it, watch make run exit 2 before the app starts, read the one ALTER that migrate --from-dump renders, run make db-sync, and watch make run pass with the app reading its new column.
47 sec space to pause f for fullscreen
Read transcript

pull-and-sync-demo: complete walkthrough

Generated from the demo script. Every command below is run verbatim by the recording.

before the pull

an orders service. its schema is an operation log in git, beside the code. make run checks our database against that log before it starts the app:

make run

a teammate pushes, we pull

a teammate added a column to orders, changed the app to read it, and pushed. we pull:

git pull -q && git show --stat --oneline HEAD

the schema change came with the code, as one operation in the log:

retrofit op show -q | cut -c1-72

make run stops

our database does not have that column. the app would fail on its first query, so make run checks first:

make run

exit status 2

exit 2, before the app started. identify read a schema-only dump of our database and reported where in the log it is: v1, with the teammate’s operation after it. the hint is the command that renders the migration. no history table was consulted: pg_dump read the database, and identify read the dump.

sync and run

the hint names migrate –from-dump. first, the script it renders:

retrofit migrate --from-dump .db.dump.sql -q

one statement. db-sync renders it from the same dump and pipes it to psql:

make db-sync

the same check now passes, and the app reads its new column:

make run

a git pull updated the log and left our database behind it. one check said so before the app ran, and one command brought it up to date.

Not shipped yet. No list, no noise, one message when it does.