Skip to content

Git extension skips branch creation for a Spec Kit project nested under a single root-level Git repo #3081

@PascalThuet

Description

@PascalThuet

Summary

In a monorepo with one Git repository at the root and a Spec Kit project in a subdirectory (e.g. apps/web/.specify/), feature-branch creation is silently skipped. The feature directory is created, but no Git branch is created or switched to, and the run reports Git repository not detected — even though a Git work tree clearly exists at the monorepo root.

This happens for any nested project, whether reached by cd-ing into it or via SPECIFY_INIT_DIR (#2892). Since SPECIFY_INIT_DIR exists specifically to target a member project from the monorepo root, this layout is now a supported path and the gap is more visible.

Environment

  • spec-kit main (487af97)
  • git extension installed

Reproduction

mkdir -p mono/apps/web/.specify && git -C mono init -q   # one .git, at the root
cd mono

source scripts/bash/common.sh
source extensions/git/scripts/bash/git-common.sh
export SPECIFY_INIT_DIR=apps/web

RR=$(get_repo_root)                          # -> .../mono/apps/web (the Spec Kit project root)
has_git "$RR" && echo true || echo false     # -> false
has_git mono  && echo true || echo false     # -> true   (git IS here)

The same false occurs with no SPECIFY_INIT_DIR, just cd apps/web: get_repo_root resolves to the nearest .specify/, which is the project root, not the Git root.

Expected

Feature-branch creation works for a nested project when a Git work tree exists at an ancestor directory (the monorepo root).

Actual

HAS_GIT=false, so create-new-feature-branch.sh derives the feature number from specs/ and creates the feature directory but skips git checkout -b (the branch block is guarded by [ "$HAS_GIT" = true ], create-new-feature-branch.sh:392). The user sees Git repository not detected; skipped branch validation (git-common.sh:33), which is inaccurate — git is present, just not at the project root.

Root cause

has_git requires .git to be a direct child of the resolved project root:

# extensions/git/scripts/bash/git-common.sh:7
has_git() {
    local repo_root="${1:-$(pwd)}"
    { [ -d "$repo_root/.git" ] || [ -f "$repo_root/.git" ]; } && \
        command -v git >/dev/null 2>&1 && \
        git -C "$repo_root" rev-parse --is-inside-work-tree >/dev/null 2>&1
}

REPO_ROOT is the Spec Kit project root (the directory containing .specify/), which in a monorepo is not the Git work tree root. The .git-direct-child test short-circuits to false before the rev-parse --is-inside-work-tree test — which would succeed, since git -C walks up to the enclosing work tree.

Possible direction

Dropping the .git-direct-child precondition and relying on git -C "$repo_root" rev-parse --is-inside-work-tree would detect the ancestor work tree. That raises a scoping question for projects that share one Git repo (branch namespacing across members, related to #1382), so the fix and its scope are worth a maintainer decision rather than a blind change. At minimum, the Git repository not detected message is misleading in this case and could distinguish "no git anywhere" from "git is at a parent of the project root".

Related


(Disclosure: AI-assisted investigation and drafting; reviewed by me.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions