HomePost

Auto-Managing .env Files in Git Worktrees

2026-02-05

Using a Git post-checkout hook to automatically copy .env files when creating worktrees

The Problem: Manually Copying .env Files Every Time

When you frequently create Git worktrees in a Bun monorepo, you run into this annoyance: every new worktree needs its .env files manually copied over. Especially when using GUI apps like oh-my-worktree to manage worktrees, having to open a terminal just to copy files each time is tedious and error-prone.

In my case, I needed two environment files:

  • apps/api-server/.env
  • apps/wetrials-x-mobile/.env

Every time I created a worktree, I had to copy these files one by one.

Approaches Considered

1. Symlinks

Keep .env files in a central location and symlink them in worktrees.

  • Pros: Changes propagate to all worktrees
  • Cons: Hard to automate with GUI apps; still need manual symlink creation per worktree

2. direnv

A tool that auto-loads environment variables per directory.

  • Pros: Powerful and flexible
  • Cons: Overkill since Bun already auto-loads .env files

3. .env.example + Auto Copy

Copy from a version-controlled .env.example to the actual .env file.

  • Pros: Team-friendly, trackable in git
  • Cons: Need to re-enter sensitive values every time

4. External .env-store Directory

Copy from a central store outside the project.

  • Pros: Clean structure
  • Cons: Requires hardcoded paths, hard to share across team members

The Solution: Git post-checkout Hook

When Git creates a worktree, it automatically runs the post-checkout hook. We can leverage this to automatically copy .env files.

Key idea:

  • Auto-copy .env files from the main worktree (bare root) to the new worktree
  • Use relative paths to avoid hardcoding
  • Skip when running in the main worktree itself

Implementation: post-checkout Hook Script

Create a .git/hooks/post-checkout file with the following content:

bash
#!/bin/bash
# Git worktree post-checkout hook
# Auto-copies .env files from bare root on worktree creation
 
BARE_ROOT="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)"
CURRENT="$(pwd)"
 
# Skip if we're in the bare root itself
[ "$BARE_ROOT" = "$CURRENT" ] && exit 0
 
# Copy .env files (only if they don't already exist)
for env_file in apps/api-server/.env apps/wetrials-x-mobile/.env; do
    if [ -f "$BARE_ROOT/$env_file" ] && [ ! -e "$env_file" ]; then
        cp "$BARE_ROOT/$env_file" "$env_file"
    fi
done

How It Works

  1. git rev-parse --git-common-dir: Returns the path to the shared .git directory across all worktrees.
  2. BARE_ROOT calculation: The parent of the common .git directory is the main worktree (bare root).
  3. Condition check: If we're already in the bare root, the original .env files are already there, so exit.
  4. File copy: Copy .env files from the bare root to the current worktree. Won't overwrite existing files.

Installation

1. Create the Hook File

Create the file in your main repository's .git/hooks/ directory:

bash
cat > .git/hooks/post-checkout << 'EOF'
#!/bin/bash
BARE_ROOT="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)"
CURRENT="$(pwd)"
 
[ "$BARE_ROOT" = "$CURRENT" ] && exit 0
 
for env_file in apps/api-server/.env apps/wetrials-x-mobile/.env; do
    if [ -f "$BARE_ROOT/$env_file" ] && [ ! -e "$env_file" ]; then
        cp "$BARE_ROOT/$env_file" "$env_file"
    fi
done
EOF

2. Make It Executable

bash
chmod +x .git/hooks/post-checkout

3. Test

Create a new worktree and verify that .env files are copied automatically:

bash
git worktree add ../test-branch test-branch
cd ../test-branch
ls -la apps/api-server/.env apps/wetrials-x-mobile/.env  # check files exist

Caveats

Won't Apply to Existing Worktrees

Worktrees created before the hook was installed didn't trigger post-checkout, so you'll need to copy .env files manually:

bash
cd /path/to/existing-worktree
cp /path/to/main-worktree/apps/api-server/.env apps/api-server/.env
cp /path/to/main-worktree/apps/wetrials-x-mobile/.env apps/wetrials-x-mobile/.env

Sharing with Team Members

The .git/hooks/ directory isn't tracked by Git by default. To share the setup with your team:

Option 1: Manual install (simple) Add installation instructions to your README and let everyone set it up.

Option 2: Shared Git hooks (recommended) Create a .githooks/ directory in the project root and commit the hooks:

bash
mkdir -p .githooks
mv .git/hooks/post-checkout .githooks/post-checkout
chmod +x .githooks/post-checkout
git add .githooks/post-checkout
git config core.hooksPath .githooks

Then other developers will automatically use the hooks after cloning.

Conclusion

Using the Git post-checkout hook, you can automatically copy .env files when creating worktrees. This approach:

  • Works perfectly with GUI apps (runs automatically)
  • No hardcoded paths, works anywhere
  • No extra tools needed (no direnv, symlinks, etc.)

A simple but effective solution that completely eliminates the hassle of manually copying files every time.

While dealing with this problem, I ended up building a macOS app to make worktree management even easier. It's called oh-my-worktree, and it has built-in .env auto-copy so you don't even need the hook setup.

oh-my-worktree .env auto-copy settings

If you're a macOS user who frequently works with worktrees, give it a try.