anthonyiles / worktree-isolation
Per-worktree test database isolation and bootstrap automation for PHP projects.
Requires
- php: ^8.2
Requires (Dev)
- illuminate/support: ^11.0|^12.0
- orchestra/testbench: ^9.0|^10.0
Suggests
- illuminate/support: Required for artisan commands (worktree:install, worktree:clean). Not needed if using the standalone bin/ scripts.
This package is auto-updated.
Last update: 2026-08-06 00:06:35 UTC
README
Per-worktree test database isolation and bootstrap automation for PHP projects.
Works with any PHP project and any development environment: native PHP (Herd, Valet), Docker Compose, Laravel Sail, or any standalone Docker image. No framework required — Laravel integration is included but optional.
The Problem
When using git worktree with a PHP project, each worktree needs:
- Composer and npm dependencies installed
- Environment files (
.env,.env.testing) configured - An isolated test database to avoid conflicts with other worktrees running in parallel
This package automates all of that. After installation, every git worktree add automatically bootstraps the new worktree — no manual steps required.
Requirements
- PHP 8.2+
- Git 2.54+ (for config-based hooks)
- MySQL (for per-worktree database isolation)
Installation
composer require anthonyiles/worktree-isolation --dev
Then run the install script with your preferred runtime:
Any PHP Project
php vendor/anthonyiles/worktree-isolation/stubs/bin/worktree-install
After the first install, re-runs are simpler since scripts are published to bin/:
php bin/worktree-install
Laravel Projects
Laravel projects get artisan integration automatically:
php artisan worktree:install
Runtime Options
All install paths accept the same runtime options:
Native PHP (default — Herd, Valet, local PHP):
php bin/worktree-install
# or: php artisan worktree:install
Docker Compose:
php bin/worktree-install --runtime=docker-compose --compose-service=app
# or: php artisan worktree:install --runtime=docker-compose --compose-service=app
Docker Image (Sail or standalone):
php bin/worktree-install --runtime=docker-image --docker-image="myapp" --docker-network="myapp_default" # or: php artisan worktree:install --runtime=docker-image --docker-image="sail-8.5/app" --docker-network="myproject_sail"
Custom Test Command
By default, tests run via php artisan test. For non-Laravel projects, set a custom test command:
php bin/worktree-install --test-command="php vendor/bin/phpunit"
Or set WORKTREE_TEST_COMMAND in .worktree-isolation.env:
WORKTREE_TEST_COMMAND=php vendor/bin/phpunit
The install command does everything:
- Verifies Git 2.54+ is installed
- Publishes
bin/worktree-setup,bin/test,bin/worktree-install, andbin/worktree-cleanscripts - Publishes the post-checkout git hook to
.githooks/ - Makes all scripts executable
- Creates/updates
.githooks.configwith the hook registration - Configures
git config --localto use the hooks - Creates
.worktree-isolation.envwith your runtime settings
For other engineers
After pulling the branch, each engineer just runs:
php bin/worktree-install
# or: php artisan worktree:install (Laravel projects)
The command is idempotent and handles everything.
How It Works
Automatic Worktree Bootstrap
When you run git worktree add, the post-checkout hook detects the new worktree and runs bin/worktree-setup, which:
- Copies
.envfrom the main repo - Copies
.env.testing(or falls back to.env.testing.example) - Forces
TEST_DB_PER_WORKTREE=truein the worktree's.env.testing - Runs
composer install(via the configured runtime) - Runs
npm install(via the configured runtime)
Per-Worktree Test Databases
When TEST_DB_PER_WORKTREE=true, bin/test derives a unique database name from the worktree directory:
testing-{worktree-folder-name}
For example, a worktree at ../worktrees/my-project/feature-auth gets database testing-feature-auth.
The database is created automatically on first test run. A safety guard ensures the derived name always contains "test" to prevent accidental use of production databases.
Running Tests
From any worktree:
bin/test # run all tests bin/test --filter=MyTest # filter tests bin/test tests/Feature/MyTest.php # specific file
Cleaning Up
Drop all per-worktree test databases:
php bin/worktree-clean
# or: php artisan worktree:clean (Laravel projects)
This lists all databases matching the {base}-* pattern and asks for confirmation before dropping them. Use --force to skip the prompt.
Configuration
Runtime Drivers
| Driver | When to use | Requirements |
|---|---|---|
native (default) |
Herd, Valet, any local PHP/Node | PHP, Composer, Node on host |
docker-compose |
Docker Compose projects | Running docker compose up -d |
docker-image |
Sail or standalone Docker image | Pre-built Docker image |
.worktree-isolation.env
Project-level configuration (committed to repo):
# Runtime driver: native | docker-compose | docker-image WORKTREE_RUNTIME=native # Test command (default: php artisan test) # WORKTREE_TEST_COMMAND=php vendor/bin/phpunit # --- docker-compose driver --- # WORKTREE_COMPOSE_SERVICE=app # WORKTREE_COMPOSE_FILE=docker-compose.yml # --- docker-image driver --- # WORKTREE_DOCKER_IMAGE=myapp # WORKTREE_DOCKER_NETWORK=myapp_default # WORKTREE_DOCKER_WORKDIR=/var/www/html # --- Common --- WORKTREE_TESTING_ENV_FILE=.env.testing WORKTREE_TESTING_ENV_EXAMPLE=.env.testing.example WORKTREE_DB_PER_WORKTREE_KEY=TEST_DB_PER_WORKTREE # Additional env vars to forward to the test container (docker-image only) # WORKTREE_EXTRA_ENV_VARS=
Laravel Config (optional)
Laravel projects can also publish a config file:
php artisan vendor:publish --tag=worktree-isolation-config
This creates config/worktree-isolation.php which mirrors the .worktree-isolation.env settings through Laravel's config system.
Published Scripts
| Script | Purpose |
|---|---|
bin/test |
Run tests with per-worktree database isolation |
bin/worktree-setup |
Bootstrap a worktree (env files, dependencies) |
bin/worktree-install |
Install/configure worktree isolation (no framework needed) |
bin/worktree-clean |
Drop per-worktree test databases (no framework needed) |
AI Agent Integration
Add this to your project's cursor rules or AGENTS.md:
**Worktrees:** If the working directory is a git worktree (`.git` is a file, not a directory), you **must** use `bin/test` instead of your usual test command. The `bin/test` script handles per-worktree database isolation and runtime dispatch.
License
MIT