Skip to content

daikiymmt/dwt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dwt - Docker Worktree

Bridge git worktrees and Docker Compose. Switch which worktree's code runs in your containers without restarting infrastructure.

Problem

When using git worktrees for parallel development, Docker Compose volume mounts (./:/app) always reference the main repository. Code changes in worktrees don't appear in running containers. Additionally, named volumes (DB, Redis, etc.) are shared across all worktrees, causing data conflicts when branches have different schemas or seed data.

Solution

dwt auto-detects services with repository bind mounts, generates a docker-compose.override.yml pointing to your worktree, isolates named volumes per branch, and recreates only the affected containers.

$ dwt switch feat/issue-2400
Switching to: feat/issue-2400-price-change-validation
Recreating services: app-server, db, mongodb, redis-primary, redis-read
Done! Containers are now using: feat/issue-2400-price-change-validation

After switching:

  • Bind mounts point to the worktree (./ -> /path/to/worktree/)
  • Named volumes are suffixed per branch (db-data -> db-data--feat-issue-2400)
  • Shared volumes (e.g., module caches) remain unchanged
  • Switching back to main removes the override, restoring original volume names

Install

go install github.com/daikiymmt/dwt/cmd/dwt@latest

Or download a binary from Releases.

Usage

# List available worktrees
dwt list

# Switch to a worktree (partial matching supported)
dwt switch 2400                    # matches feat/issue-2400-xxx

# Check current state
dwt status

# Switch back to main repository
dwt switch main

# Preview changes without applying
dwt switch 2400 --dry-run --verbose

# Generate optional config file
dwt init

How It Works

  1. Detect: Parses docker-compose.yml to find services with bind mounts from the repository (./, ./src/, ./config/file.yml, etc.) and services with named volumes
  2. Override: Generates docker-compose.override.yml that:
    • Rewrites bind mount sources to the worktree's absolute path
    • Suffixes named volumes with the branch name (db-data -> db-data--feat-issue-2400)
    • Keeps shared volumes (e.g., module caches) unchanged
  3. Recreate: Runs docker compose up -d for detected services, respecting depends_on order and healthchecks
  4. Track: Records active worktree in .dwt-active

Volume Isolation

Named volumes are automatically isolated per worktree branch:

Volume Worktree feat/issue-2400 Main
db-data db-data--feat-issue-2400 db-data
mongo-data mongo-data--feat-issue-2400 mongo-data
redis-volume redis-volume--feat-issue-2400 redis-volume
go-mod-cache (shared) go-mod-cache go-mod-cache

Worktree-specific volumes persist on disk. When you switch back to the same worktree, existing data is reused. Clean up unused volumes with docker volume prune.

Auto-Detection

Mount Detected Reason
./:/app Yes Repository root bind mount
./build/nginx.conf:/etc/nginx/nginx.conf Yes Repository file bind mount
./scripts/init:/docker-entrypoint-initdb.d Yes Repository directory bind mount
go-mod-cache:/go/pkg/mod Yes Named volume (isolated)
db-data:/var/lib/mysql Yes Named volume (isolated)
redis-volume:/data Yes* Named volume (volume-only service, included if running)

* Services with only named volumes (no bind mounts) are included when running, skipped when stopped.

Configuration (Optional)

By default, dwt auto-detects everything. For projects that need customization, create .dwt.yml:

# Only switch these specific services
services:
  - app-server
  - worker

# Custom compose file path
compose_file: docker-compose.yml

# Volumes shared across worktrees (not isolated)
shared_volumes:
  - go-mod-cache

# Commands to run after switching
hooks:
  post-switch:
    - make migrate-up

Generate it automatically:

dwt init

Safety

  • Selective recreate: Only recreates detected services. Unrelated services keep running.
  • Backup: If a non-dwt docker-compose.override.yml exists, it's backed up to .dwt-backup and restored on dwt switch main
  • Profiles: Services with Docker Compose profiles are only included if already running
  • --dry-run: Preview all changes before applying

Requirements

  • Git
  • Docker Compose v2+ (docker compose command)

.gitignore

Add these to your .gitignore:

docker-compose.override.yml
.dwt-active
.dwt.yml

License

MIT

About

Bridge git worktrees and Docker Compose. Switch code, DB, and cache volumes per branch.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors