Copy .env files into a new git worktree
worktree branch and worktree checkout copy your local environment files into a new worktree so it is
usable without a round of manual setup.
What Gets Copied
Section titled “What Gets Copied”A file is copied when both of these are true:
- Its name is env-shaped —
.envand anything starting with it (.env.local,.env.development,.env.production,.env.test,.env.staging, and the.env.*.localoverride layer),.dev.varsand anything starting with it (Cloudflare Wrangler), or.envrc(direnv). - Git is not carrying it — the file is untracked and matched by your ignore rules.
The second condition is what keeps the behaviour predictable. A committed .env.example is already in the
new worktree because git checked it out, so it is never copied over itself. Anything git ignores would
otherwise be missing entirely, which is exactly what this feature exists to fix.
Files are matched anywhere in the repository, not just at the root, and land at the same relative path in
the new worktree — docs/worker/.dev.vars arrives as docs/worker/.dev.vars. Directories that exist only
because of ignored files are created as needed.
Submodules are not searched, because git does not look inside one when listing the parent’s files. An env file inside a submodule has to be copied by hand.
Nested git repositories (a linked worktree, or a git init) are not searched either, for the same reason,
and that applies to copy patterns too. A file inside one has to be copied by hand.
node_modules is excluded, so an env file shipped inside a dependency is never copied.
Other files, from .worktree.yml
Section titled “Other files, from .worktree.yml”Not every secret is env-shaped. A repository can list more files under copy in its
project configuration:
copy: - config/master.keyEach entry is a relative glob, and a file is copied under the same two conditions as above: it is untracked and
matched by your ignore rules. A copy path must be gitignored to be copied — a tracked file is already in
the new worktree, and a file git neither tracks nor ignores is left behind. These files are reported in the
same list as env files, and worktree checkout copies them too.
Check What Gets Copied
Section titled “Check What Gets Copied”Every copied file is listed by path, so the output is worth a glance:
Copying 4 env files from /Users/you/code/acme: ✔ .env ✔ .env.local ✔ docs/worker/.dev.vars ✔ tmp/backup/.env.oldNothing here is curated — files are selected by name shape and your ignore rules, not from a list anyone
maintains. That is the point, and it is also why the list matters: a stray .env.old someone dumped years
ago, or a colleague’s .env.production, is copied like anything else. If a path in that list surprises you,
that file has been sitting in your main checkout all along.
The whole report goes to standard output, heading included, so it survives a pipe or a redirect if you want to keep a record of what a worktree was given.
A path that would not read back as itself is shown quoted and escaped, rather than printed raw:
Copying 2 env files from /Users/you/code/acme: ✔ " lead/.env" ✔ .envThat first name really does begin with a space. Left bare it would look like nothing more than a misaligned column, which is no use in a list whose job is to make an unexpected file stand out.
When nothing matches, the command says so rather than staying silent:
No env files to copy from /Users/you/code/acmeBest Practices
Section titled “Best Practices”- Keep secrets out of source control — this feature assumes your env files are gitignored, and only copies the ones that are.
- Review copied env values when switching contexts. A
.envpointing at a staging database follows you into every new worktree. - Commit an
.env.exampleso required variables are documented. It is carried by git, not by this copy. - Use team conventions for required variables.
If A File Is Not Copied
Section titled “If A File Is Not Copied”Check that git actually ignores it:
git check-ignore -v .env.stagingNo output means the file is not ignored, so it is not copied. Add it to .gitignore. The same applies to a
file named under copy.
If the command printed output, the file is ignored, but it is still left behind when it sits inside a nested git repository, as described under What Gets Copied. Copy it by hand.
A symlink is copied as the file it points at, so the new worktree gets a plain file with the same content. A symlink that points at a directory, or at nothing, is skipped and not listed; the files after it are still copied.