Skip to content

netlify dev fails to detect repository root in git worktrees #7868

@ffaubert

Description

@ffaubert

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugcode to address defects in shipped code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions