Schema Merge
The merge command applies schema changes from one branch to another.
pgbranch merge <source> <target> [flags]Arguments
Section titled “Arguments”| Argument | Description |
|---|---|
source | Branch containing the changes to apply |
target | Branch to apply changes to |
| Flag | Short | Description | Default |
|---|---|---|---|
--dry-run | - | Show SQL without applying changes | false |
--migration-file | - | Generate a migration file instead of applying | false |
--migration-dir | - | Directory for migration files | migrations |
--force | -f | Skip confirmation prompts | false |
Examples
Section titled “Examples”Preview Changes (Dry Run)
Section titled “Preview Changes (Dry Run)”Always start with a dry run:
pgbranch merge feature-auth main --dry-runOutput:
-- Dry Run: Changes that would be applied to 'main'-- Source: feature-auth
CREATE TYPE auth_provider AS ENUM ('local', 'google', 'github');
CREATE TABLE sessions ( id uuid NOT NULL DEFAULT gen_random_uuid(), user_id uuid NOT NULL, token text NOT NULL, expires_at timestamp with time zone, PRIMARY KEY (id));
ALTER TABLE users ADD COLUMN last_login timestamp with time zone;ALTER TABLE users ADD COLUMN login_count integer DEFAULT 0;
CREATE INDEX sessions_user_id_idx ON sessions(user_id);
ALTER TABLE sessions ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);
-- No changes applied (dry run mode)Apply Changes
Section titled “Apply Changes”After reviewing the dry run:
pgbranch merge feature-auth mainOutput:
Merging schema changes from 'feature-auth' to 'main'
Changes to apply: + 1 table + 2 columns + 1 index + 1 foreign key + 1 enum type
Apply these changes? [y/N]: y
Applying changes...✓ Created enum type: auth_provider✓ Created table: sessions✓ Added column: users.last_login✓ Added column: users.login_count✓ Created index: sessions_user_id_idx✓ Added foreign key: sessions_user_id_fkey
Schema merge complete!Generate Migration File
Section titled “Generate Migration File”Instead of applying changes directly, generate a migration file:
pgbranch merge feature-auth main --migration-fileOutput:
Migration file created: migrations/20240115143022_merge_feature_auth_to_main.sqlThe generated file:
-- Migration: feature-auth → main-- Generated by pgbranch at 2024-01-15 14:30:22
-- Create enum typeCREATE TYPE auth_provider AS ENUM ('local', 'google', 'github');
-- Create table: sessionsCREATE TABLE sessions ( id uuid NOT NULL DEFAULT gen_random_uuid(), user_id uuid NOT NULL, token text NOT NULL, expires_at timestamp with time zone, PRIMARY KEY (id));
-- Add columns to usersALTER TABLE users ADD COLUMN last_login timestamp with time zone;ALTER TABLE users ADD COLUMN login_count integer DEFAULT 0;
-- Create indexesCREATE INDEX sessions_user_id_idx ON sessions(user_id);
-- Add foreign keysALTER TABLE sessions ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);Custom Migration Directory
Section titled “Custom Migration Directory”pgbranch merge feature-auth main --migration-file --migration-dir db/migrationsForce Merge (Skip Confirmation)
Section titled “Force Merge (Skip Confirmation)”pgbranch merge feature-auth main --forceDestructive Changes
Section titled “Destructive Changes”When the merge includes destructive changes, pgbranch displays extra warnings:
pgbranch merge main feature-cleanupOutput:
Merging schema changes from 'main' to 'feature-cleanup'
⚠️ DESTRUCTIVE CHANGES DETECTED:
The following changes may result in data loss: - DROP TABLE legacy_sessions - DROP COLUMN users.deprecated_field - DROP INDEX users_old_email_idx
Changes to apply: - 1 table (DESTRUCTIVE) - 1 column (DESTRUCTIVE) - 1 index (DESTRUCTIVE)
Type 'yes' to confirm destructive changes: yes
Applying changes...How Merge Works
Section titled “How Merge Works”The merge process:
- Computes diff between source and target branches
- Generates SQL to transform target schema to match source
- Validates SQL for syntax and dependency order
- Applies changes to the target branch’s template database
- Updates metadata to record the merge
Source: feature-auth Target: main │ │ │ │ └──────── DIFF ───────────────┘ │ ▼ Generate SQL │ ▼ Apply to target template database │ ▼ main now has feature-auth schemaMerge Strategy
Section titled “Merge Strategy”pgbranch uses an additive merge strategy by default:
- Additions are applied (new tables, columns, etc.)
- Modifications are applied (type changes, constraint changes)
- Deletions require explicit confirmation
This minimizes accidental data loss.
Limitations
Section titled “Limitations”No Data Migration
Section titled “No Data Migration”Schema merge only handles schema changes, not data:
- New columns are added with NULL or default values
- Data from the source branch is not copied
- Custom data migrations must be handled separately
Conflict Resolution
Section titled “Conflict Resolution”pgbranch does not automatically resolve conflicts:
- If both branches modified the same column differently, you must resolve manually
- Complex schema changes may require manual SQL
Rollback
Section titled “Rollback”There is no automatic rollback for failed merges. Before merging:
# Create a backup branchpgbranch checkout mainpgbranch branch main-backup
# Then mergepgbranch merge feature-auth main
# If something goes wrongpgbranch checkout main-backuppgbranch delete main --forcepgbranch branch main # Recreate from backupBest Practices
Section titled “Best Practices”Always Dry Run First
Section titled “Always Dry Run First”pgbranch merge source target --dry-runReview Generated SQL
Section titled “Review Generated SQL”Check the generated SQL for correctness before applying.
Create Backup Branches
Section titled “Create Backup Branches”pgbranch branch target-backuppgbranch merge source targetUse Migration Files for Production
Section titled “Use Migration Files for Production”For changes that need to go to production:
pgbranch merge feature target --migration-fileThen apply the migration file through your normal deployment process.
Test on a Copy
Section titled “Test on a Copy”# Create test branchpgbranch checkout targetpgbranch branch target-test
# Test mergepgbranch merge source target-test
# Verify everything works# Then merge to real targetpgbranch merge source target