LogoSkills

serverpod:merge-migrations

Merge multiple migrations into one (cleanup before production deployment)

ํ•ญ๋ชฉ๋‚ด์šฉ
Invoke/serverpod:merge-migrations
Categoryserverpod
Complexitymoderate

/serverpod:merge-migrations โ€” ํฉ์–ด์ง„ DB ๋ณ€๊ฒฝ ๊ธฐ๋ก์„ ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๊ธฐ#

ํ•œ๋งˆ๋””๋กœ#

๊ฐœ๋ฐœํ•˜๋ฉด์„œ ์กฐ๊ธˆ์”ฉ ์Œ“์ธ ์—ฌ๋Ÿฌ ๊ฐœ์˜ "DB ๋ณ€๊ฒฝ ๊ธฐ๋ก(๋งˆ์ด๊ทธ๋ ˆ์ด์…˜)"์„ ํ•˜๋‚˜๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋ฌถ์–ด์ฃผ๋Š” ์ •๋ฆฌ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์žฅ์œผ๋กœ ์ฐข์–ด์ง„ ์˜์ˆ˜์ฆ์„ ํ•œ ์žฅ์œผ๋กœ ์ •๋ฆฌํ•ด ๋‘๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”. ์šด์˜(์‹ค์„œ๋น„์Šค) ์„œ๋ฒ„์—๋Š” ์†๋Œ€์ง€ ์•Š๊ณ , ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋งŒ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋ˆ„๊ฐ€ยท์–ธ์ œ ์“ฐ๋‚˜์š”#

  • ๊ฐœ๋ฐœ ์ค‘์— DB ๊ตฌ์กฐ ๋ณ€๊ฒฝ ๊ธฐ๋ก์ด ์—ฌ๋Ÿฌ ๊ฐœ๋กœ ์ž˜๊ฒŒ ์Œ“์—ฌ์„œ, ์‹ค์„œ๋น„์Šค ๋ฐฐํฌ ์ „์— ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ
  • ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํžˆ์Šคํ† ๋ฆฌ(๋ณ€๊ฒฝ ์ด๋ ฅ)๊ฐ€ ์ง€์ €๋ถ„ํ•ด์„œ ๋ณด๊ธฐ ์ข‹๊ฒŒ ํ•ฉ์น˜๊ณ  ์‹ถ์„ ๋•Œ

๐Ÿ‘‰ ๋ฐฑ์—”๋“œ(Serverpod) ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด๋ฏธ ์šด์˜ ์„œ๋ฒ„์— ๋ฐ˜์˜๋œ ๊ธฐ๋ก์€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  ๊ทธ ์ดํ›„์— ์ƒ๊ธด ๊ฐœ๋ฐœ์šฉ ๊ธฐ๋ก๋“ค๋งŒ ํ•ฉ์นฉ๋‹ˆ๋‹ค.

๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”#

์—ฌ๋Ÿฌ ๊ฐœ๋กœ ๋‚˜๋‰œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ํ•˜๋‚˜์˜ ์ƒˆ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์œผ๋กœ ํ•ฉ์ณ์ค๋‹ˆ๋‹ค. ๊ตฌ์ฒด์ ์œผ๋กœ:

  • ํ•ฉ์น˜๊ธฐ ์ „์— ๊ธฐ์กด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ migrations_backup/ ํด๋”์— ์ž๋™ ๋ฐฑ์—…
  • ์ƒˆ๋กœ ํ•ฉ์ณ์ง„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํด๋” 1๊ฐœ ์ƒ์„ฑ (๊ทธ ์•ˆ์— definition.sql, migration.sql ๋“ฑ ์‹ค์ œ ํŒŒ์ผ๋“ค)
  • ๋ณ€๊ฒฝ ์ด๋ ฅ ๋ชฉ๋ก ํŒŒ์ผ์ธ migration_registry.txt ์ž๋™ ๊ฐฑ์‹ 
  • ์šด์˜ ์„œ๋ฒ„์— ์ด๋ฏธ ๋ฐ˜์˜๋œ ๊ธฐ์ค€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜(--base)์€ ๊ทธ๋Œ€๋กœ ๋ณด์กด

์–ด๋–ป๊ฒŒ ์“ฐ๋‚˜์š”#

# ๊ธฐ๋ณธ: ๊ธฐ์ค€(--base) ์ดํ›„์— ์ƒ๊ธด ๋ชจ๋“  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ž๋™์œผ๋กœ ์ฐพ์•„ ํ•ฉ์น˜๊ธฐ
/serverpod:merge-migrations --base 20251223123500000

# ํ•ฉ์น  ๋ฒ”์œ„๋ฅผ ์ง์ ‘ ์ง€์ • (์‹œ์ž‘~๋)
/serverpod:merge-migrations \
  --base 20251223123500000 \
  --from 20251229134213396 \
  --to 20260113023207235

# ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋งŒ (์‹ค์ œ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ๊ฒฐ๊ณผ๋งŒ ํ™•์ธ)
/serverpod:merge-migrations --base 20251223123500000 --dry-run
  • --base (ํ•„์ˆ˜): ์šด์˜ ์„œ๋ฒ„์— ์ด๋ฏธ ์ ์šฉ๋œ ๊ธฐ์ค€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ID. ์ด ID๋Š” ์ ˆ๋Œ€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์œผ๋ฉฐ, ์ด ์‹œ์  ์ดํ›„์˜ ๊ฐœ๋ฐœ์šฉ ๊ธฐ๋ก๋งŒ ์ •๋ฆฌ ๋Œ€์ƒ์ด ๋ฉ๋‹ˆ๋‹ค.
  • --from / --to: ํ•ฉ์น  ์‹œ์ž‘ยท๋ ์ง€์ . ๋น„์›Œ๋‘๋ฉด ์ž๋™์œผ๋กœ ์žก์•„์ค๋‹ˆ๋‹ค.
  • --name: ํ•ฉ์ณ์ง„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์— ๋ถ™์ผ ์ด๋ฆ„.
  • --dry-run: ์‹ค์ œ ๋ณ€๊ฒฝ ์—†์ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋งŒ ํ•ฉ๋‹ˆ๋‹ค.

์•ˆ์—์„œ ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋‚˜์š”#

  1. ๋ถ„์„ โ€” ๊ธฐ์ค€(--base) ์ดํ›„์— ์ƒ๊ธด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๋“ค์„ ๋ชจ์•„, ์–ด๋–ค ํ…Œ์ด๋ธ”์ด ๋ฐ”๋€Œ๋Š”์ง€ ํ‘œ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  2. ํ•ฉ์น˜๊ธฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ€” ํฉ์–ด์ง„ ๋ณ€๊ฒฝ ๋‚ด์šฉ(SQL)์„ ํ•˜๋‚˜๋กœ ํ•ฉ์ณค์„ ๋•Œ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ๋ฏธ๋ฆฌ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  3. ์‚ฌ์šฉ์ž ํ™•์ธ โ€” "๊ธฐ์กด ํŒŒ์ผ์ด ์‚ญ์ œ๋˜๊ณ  ๋กœ์ปฌ์—์„œ๋งŒ ์‹คํ–‰๋œ๋‹ค"๋Š” ์ฃผ์˜์‚ฌํ•ญ์„ ์•ˆ๋‚ดํ•˜๊ณ , ์ง„ํ–‰ํ• ์ง€(Y/n) ๋ฌผ์–ด๋ด…๋‹ˆ๋‹ค.
  4. ์‹คํ–‰ โ€” ๊ธฐ์กด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋ฐฑ์—…ํ•œ ๋’ค ์‚ญ์ œํ•˜๊ณ , ํ•ฉ์ณ์ง„ ์ƒˆ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋งŒ๋“ค๊ณ , ์ด๋ ฅ ๋ชฉ๋ก์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
  5. ๊ฒ€์ฆ โ€” ํ•ฉ์น˜๊ธฐ ์™„๋ฃŒ ๊ฒฐ๊ณผ์™€ ๋ฐฑ์—… ์œ„์น˜, ๋‹ค์Œ์— ํ•  ์ผ(๋กœ์ปฌ DB ์žฌ์„ค์ •ยท์ปค๋ฐ‹)์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

์šด์˜ ์„œ๋ฒ„๋Š” ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šด์˜ DB๋Š” ์ด๋ฏธ ์ ์šฉ๋œ ๊ธฐ๋ก์„ ๋”ฐ๋กœ ๊ด€๋ฆฌ(serverpod_migrations ํ…Œ์ด๋ธ”)ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ, ํ•ฉ์ณ์ง„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์€ ์ƒˆ ํ™˜๊ฒฝ์—์„œ๋งŒ ์“ฐ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํŒ€์›๊ณผ ๋™์‹œ์— ์ž‘์—…ํ•˜๋ฉด ์ถฉ๋Œ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์œผ๋‹ˆ, ํ•ฉ์น˜๊ธฐ ์ „์— ํŒ€์›๊ณผ ์กฐ์œจํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.


โš™๏ธ ์ƒ์„ธ ์˜ต์…˜ยท์‹คํ–‰ ๋ช…์„ธ (๊ฐœ๋ฐœ์ž / AI ์—์ด์ „ํŠธ์šฉ)

Triggers#

  • When cleaning up migrations before production deployment
  • When consolidating multiple development migrations into one
  • When cleaning up migration history

Context Trigger Pattern#

/serverpod:merge-migrations --base {production_migration} [--options]

Parameters#

ParameterRequiredDescriptionExample
--baseโœ…Production baseline migration ID (this ID is preserved)20251223123500000
--fromโŒMerge start migration (auto-detected after base if not specified)20251229134213396
--toโŒMerge end migration (auto-detected as latest if not specified)20260113023207235
--nameโŒMerged migration nameconsolidated_dev
--dry-runโŒPreview only without actual changestrue/false

Note: --base is always required. Specify the production-applied migration ID to only merge development migrations after that point.

Behavioral Flow#

Step 1: Migration Analysis#

## Migration Analysis

**Production baseline**: {base_migration}
**Merge targets**: {count}

| # | Migration ID | Created | Changed Tables |
|---|-------------|---------|----------------|
| 1 | 20251229134213396 | 2025-12-29 | coupon |
| 2 | 20260112140301453 | 2026-01-12 | author |
| 3 | 20260113023207235 | 2026-01-13 | author |

**Affected tables**: coupon, author

Step 2: SQL Merge#

## SQL Merge Preview

### Before merge (individual migrations)
sql

-- Migration 1: 20251229134213396 ALTER TABLE "coupon" ADD COLUMN "new_field" text;

-- Migration 2: 20260112140301453 ALTER TABLE "author" ADD COLUMN "memo" text;

-- Migration 3: 20260113023207235 ALTER TABLE "author" ADD COLUMN "extra" text;


 ### After merge (single migration)
sql

-- Migration: {new_migration_id} BEGIN;

ALTER TABLE "coupon" ADD COLUMN "new_field" text; ALTER TABLE "author" ADD COLUMN "memo" text; ALTER TABLE "author" ADD COLUMN "extra" text;

-- MIGRATION VERSION FOR kobic INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") VALUES ('kobic', '{new_migration_id}', now()) ON CONFLICT ("module") DO UPDATE SET "version" = '{new_migration_id}', "timestamp" = now();

COMMIT;

Step 3: User Confirmation#

## Merge Confirmation

**Caution**:
- This operation deletes existing migration files
- Run only on local development DB
- Existing migrations must already be applied to the production DB

**Proceed with merge? (Y/n)**

Step 4: Execute Merge#

# 1. Backup existing migrations
mkdir -p migrations_backup
for dir in migrations/{from} migrations/{middle} migrations/{to}; do
  cp -r  " $dir "   migrations_backup/
done

# 2. Delete existing migrations
rm -rf migrations/{from}
rm -rf migrations/{middle}
rm -rf migrations/{to}

# 3. Create new migration
serverpod create-migration --experimental-features=all

# 4. Update migration_registry.txt
# Remove old migration IDs, add new ID

Step 5: Verification#

## Merge Complete

Existing migrations backed up: `migrations_backup/`
New migration created: `{new_migration_id}`
migration_registry.txt updated

### Next Steps

1. **Reset local DB** (optional):
   
bash

Recreate local DB from scratch#

melos run backend:pod:run-migration


 2. **Commit changes**:
   
bash

git add backend/kobic_server/migrations/ git commit -m "chore(migration): merge migrations ({from}~{to} โ†’ {new_id})"


 ### Backup Location
Existing migrations are stored in `migrations_backup/`

Output Files#

backend/kobic_server/
โ”œโ”€โ”€ migrations/
โ”‚   โ”œโ”€โ”€ {base_migration}/           # Production (preserved)
โ”‚   โ”œโ”€โ”€ {new_migration}/            # Newly created merged migration
โ”‚   โ”‚   โ”œโ”€โ”€ definition.json
โ”‚   โ”‚   โ”œโ”€โ”€ definition.sql
โ”‚   โ”‚   โ”œโ”€โ”€ definition_project.json
โ”‚   โ”‚   โ”œโ”€โ”€ migration.json
โ”‚   โ”‚   โ””โ”€โ”€ migration.sql
โ”‚   โ””โ”€โ”€ migration_registry.txt      # Updated
โ”œโ”€โ”€ migrations_backup/              # Backup (can be deleted)
โ”‚   โ”œโ”€โ”€ {old_migration_1}/
โ”‚   โ”œโ”€โ”€ {old_migration_2}/
โ”‚   โ””โ”€โ”€ ...

Manual Merge Guide (Instead of Script)#

If the skill does not auto-execute, follow these steps manually:

1. Check Current State#

# Check migration_registry.txt
cat backend/kobic_server/migrations/migration_registry.txt

# Check post-production migrations
ls -la backend/kobic_server/migrations/ | grep  " 2026 "

2. Backup and Delete Existing Migrations#

cd backend/kobic_server

# Backup
mkdir -p migrations_backup
mv migrations/20251229134213396 migrations_backup/
mv migrations/20260112140301453 migrations_backup/
mv migrations/20260113023207235 migrations_backup/

# Remove the corresponding lines from migration_registry.txt
# Manually edit to remove the migration IDs to be deleted

3. Create New Migration#

# Code generation (based on current models)
melos run backend:pod:generate

# Create new migration
melos run backend:pod:create-migration

4. Verify#

# Check new migration
ls -la backend/kobic_server/migrations/ | tail -5

# Check migration_registry.txt
tail backend/kobic_server/migrations/migration_registry.txt

Examples#

Basic usage (production baseline)#

Auto-detect and merge all migrations after --base:

/serverpod:merge-migrations --base 20251223123500000

Range specification#

Merge specific range based on --base (after base ~ to):

/serverpod:merge-migrations \
  --base 20251223123500000 \
  --from 20251229134213396 \
  --to 20260113023207235

Dry-run (preview)#

Preview merged content without actual changes:

/serverpod:merge-migrations --base 20251223123500000 --dry-run

Core Rules#

  1. Production baseline: Do not touch production-applied migrations
  2. Backup required: Always backup before deletion
  3. Local only: Never run on production DB
  4. Order preserved: Migration order is automatically managed by timestamp
  5. Verification required: Verify with melos run backend:pod:generate after merge

Cautions#

Production DB caution:

  • Existing migrations are already applied to the production DB
  • Merged migrations are only used in new environments
  • Existing production is unaffected (references serverpod_migrations table)

Team collaboration:

  • Migration conflicts possible with other developers
  • Coordinate with team members before merging
  • Check migration_registry.txt conflicts before PR merge