netlify / netlify/cli

netlify dev fails to detect repository root in git worktrees

Open
#7,868 0 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: bug
Dominant language
TypeScript
Stars
1.9k
Forks
474
Avg merge
23h 30m
Merged PRs (30d)
53

Description

Describe the bug

netlify dev fails to detect repository root in git worktrees

Description

The Netlify CLI fails to properly detect the repository root when running inside a git worktree. This causes netlify dev to fall back to the user's home directory as the cwd, breaking all relative path resolution in netlify.toml and preventing the CLI from fetching environment variables from Netlify.

Environment

  • netlify-cli version: 23.13.3
  • OS: macOS (darwin-arm64)
  • Node: v22.21.1

Steps to Reproduce

  1. Create a git worktree from an existing repository:

    cd ~/git/my-repo
    git worktree add ~/git/my-repo-worktree some-branch
    
  2. Run netlify link in the worktree to link a site

  3. Run netlify dev (or netlify dev --cwd ./apps/my-app for monorepos):

    cd ~/git/my-repo-worktree
    netlify dev
    

Expected Behavior

The CLI should detect ~/git/my-repo-worktree as the repository root and resolve all paths relative to it.

Actual Behavior

The CLI falls back to the user's home directory (/Users/username) as the cwd:

❯ Initial build environment
config: /Users/frank/git/knowfun-sandbox/apps/app-shareyourfans/netlify.toml
context: dev
cwd: /Users/frank    # <-- Should be /Users/frank/git/knowfun-sandbox

This causes multiple failures:

  1. Path resolution errors:

    Base directory does not exist: /Users/frank/apps/app-shareyourfans
    
  2. Environment variables not loaded:

    Warning: Could not find account for project 'undefined' with account slug 'undefined'
    
  3. Plugin resolution failures:

    Plugin could not be found using local path: ../../netlify/plugins/netlify-plugin-bundle-env
    
  4. Monorepo workspace detection fails:

    [project.ts]: detectFrameworksInPath - undefined
    

Root Cause

The issue is in @netlify/config at lib/options/repository_root.js:

export const getRepositoryRoot = async function ({ repositoryRoot, cwd }) {
    if (repositoryRoot !== undefined) {
        return repositoryRoot;
    }
    const repositoryRootA = await findUp('.git', { cwd, type: 'directory' });
    if (repositoryRootA === undefined) {
        return cwd;
    }
    return dirname(repositoryRootA);
};

The findUp call specifies type: 'directory', but in a git worktree, .git is a file (not a directory) containing a pointer to the main repository:

# Contents of .git file in a worktree
gitdir: /Users/frank/git/my-repo/.git/worktrees/my-repo-worktree

Since findUp is looking for a directory and .git is a file, it never finds it and falls back to cwd — which through some other code path ends up as the user's home directory.

Suggested Fix

Modify the findUp call to find both files and directories by removing the type constraint:

const repositoryRootA = await findUp('.git', { cwd });

Or explicitly handle both cases:

const repositoryRootA = await findUp('.git', { cwd, type: 'directory' })
    ?? await findUp('.git', { cwd, type: 'file' });

Workaround

Users can patch their local installation:

sed -i '' "s/, type: 'directory'//" node_modules/netlify-cli/node_modules/@netlify/config/lib/options/repository_root.js

Or set the REPOSITORY_ROOT environment variable (though this alone doesn't fully fix the issue since monorepo detection still fails):

REPOSITORY_ROOT=/path/to/worktree netlify dev

Additional Context

Git worktrees are commonly used for:

  • Working on multiple branches simultaneously
  • Testing changes in isolation without stashing
  • Running long builds while continuing development

This is a significant workflow that should be supported by the CLI.

Steps to reproduce

See Claude's writeup above

Configuration

[build]
publish = "dist/"
command = "npm run build"
edge_functions = "src/edge-functions/"

[build.environment]
NODE_VERSION = "22.18.0"
NPM_VERSION = "11.5.2"
NODE_SOURCEMAP = "true"
NODE_OPTIONS = "--max_old_space_size=4096"

[functions]
node_bundler = "esbuild"
directory = "src/functions/"
external_node_modules = ["@sentry/serverless", "@block65/webcrypto-web-push"]
deno_import_map = "deno-import-map.json"

[dev]
command = "vite"
targetPort = 5175
port = 8887
autoLaunch = false

[[plugins]]
package = "../../netlify/plugins/netlify-plugin-bundle-env"

[[redirects]]
from = "/service-worker.js.map"
to = "/index.html"
status = 404
force = true

[[redirects]]
from = "/*"
to = "/index.html"
status = 200

[[headers]]
for = "/dev-sw.js"
[headers.values]
Cache-Control = "no-cache"

[[headers]]
for = "/service-worker.js"
[headers.values]
Cache-Control = "no-cache"

Environment

System:
OS: macOS 26.2
CPU: (16) arm64 Apple M4 Max
Memory: 50.29 GB / 128.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.21.1 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 11.7.0 - /usr/local/bin/npm
pnpm: 7.27.0 - /usr/local/bin/pnpm
bun: 1.3.6 - /opt/homebrew/bin/bun
Deno: 2.4.5 - /Users/frank/.deno/bin/deno

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with @netlify/config/lib/options/repository_root.js and reproduce the lookup from a Git worktree containing a .git file. Check how findUp handles the worktree marker and verify that netlify dev uses the worktree root for relative paths, environment variables, plugins, and monorepo detection.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, javascript
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.