Skip to content

feat: make git extension opt-in and remove --no-git at v0.10.0#2873

Open
Copilot wants to merge 13 commits into
mainfrom
copilot/make-git-extension-opt-in
Open

feat: make git extension opt-in and remove --no-git at v0.10.0#2873
Copilot wants to merge 13 commits into
mainfrom
copilot/make-git-extension-opt-in

Conversation

Copilot AI commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Finalizes the git extension default change at v0.10.0: specify init no longer auto-installs the bundled git extension, and the deprecated --no-git flag is removed. Users who want the git extension must opt in via specify extension add git.

Core changes

  • src/specify_cli/commands/init.py

    • Remove --no-git parameter and its deprecation warning block
    • Remove git extension auto-installation (ExtensionManager.install_from_directory for git) from the init flow
    • Remove git_default_notice variable and the "Notice: Git Default Changing" panel
    • Remove --branch-numbering parameter (now managed entirely by the git extension's config)
    • Remove git repository initialization — git init is now the git extension's responsibility (via its speckit.git.initialize command)
    • Remove the "git" tracker step entirely (no git-related work happens during init)
  • scripts/bash/common.sh / scripts/powershell/common.ps1

    • Remove branch-name validation (check_feature_branch / Test-FeatureBranch) from check-prerequisites
    • Replace git-based feature resolution with explicit state: SPECIFY_FEATURE_DIRECTORY env var or .specify/feature.json
    • Add _persist_feature_json / Save-FeatureJson helpers for writing feature state
    • Update error messages to reference SPECIFY_FEATURE_DIRECTORY (not SPECIFY_FEATURE)

Tests

  • TestGitExtensionAutoInstall → replaced with TestGitExtensionOptIn:
    • test_git_extension_not_auto_installed — extension dir absent after plain specify init
    • test_no_git_flag_is_rejected--no-git now exits non-zero (unknown option)
    • test_git_extension_commands_not_registered_by_default — no speckit-git-* skills after init
  • Removed --no-git from all other test invocations throughout tests/integrations/test_cli.py

Docs & changelog

  • docs/reference/core.md: removed --no-git row from options table and the pre-v0.10.0 NOTE; updated examples
  • docs/upgrade.md: updated Scenario 4 (no-git projects); removed the ## Using --no-git Flag section
  • docs/local-development.md: updated common-issues table
  • CHANGELOG.md: added ## [0.10.0] - TBD section documenting both breaking changes

Closes #2887

Copilot AI requested review from Copilot and removed request for Copilot June 5, 2026 17:20
Copilot AI linked an issue Jun 5, 2026 that may be closed by this pull request
5 tasks
Copilot AI requested review from Copilot and removed request for Copilot June 5, 2026 17:29
Copilot AI changed the title [WIP] Finalize git extension as opt-in and remove --no-git flag feat(init)!: make git extension opt-in and remove --no-git at v0.10.0 Jun 5, 2026
Copilot finished work on behalf of mnriem June 5, 2026 17:31
Copilot AI requested a review from mnriem June 5, 2026 17:31
@mnriem mnriem requested a review from Copilot June 5, 2026 19:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR finalizes the v0.10.0 breaking change around Git behavior during specify init: the bundled git extension is no longer auto-installed, and the deprecated --no-git flag is removed, while git repository initialization (git init) still occurs when git is available and no repo exists.

Changes:

  • Removes --no-git from the init command and drops bundled git extension auto-installation from the init flow.
  • Updates integration tests to stop passing --no-git and adds new opt-in assertions around the git extension.
  • Updates docs/changelog to reflect the new “git extension is opt-in” behavior and the flag removal.
Show a summary per file
File Description
src/specify_cli/commands/init.py Removes the --no-git flag and bundled git extension auto-install; keeps git init when available.
tests/integrations/test_cli.py Removes --no-git usage and replaces auto-install tests with opt-in expectations.
docs/upgrade.md Updates upgrade guidance for projects previously relying on --no-git.
docs/reference/core.md Removes --no-git from specify init reference and updates notes/examples.
docs/local-development.md Updates troubleshooting guidance related to the git step.
CHANGELOG.md Adds a v0.10.0 entry documenting the breaking changes.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 6/6 changed files
  • Comments generated: 5

Comment thread CHANGELOG.md Outdated
Comment thread docs/upgrade.md Outdated
Comment thread tests/integrations/test_cli.py
Comment thread tests/integrations/test_cli.py Outdated
Comment thread src/specify_cli/commands/init.py
- Remove --no-git parameter from specify init command
- Remove git extension auto-installation from init flow
- Git repository initialization (git init) still runs when git is available
- Remove --no-git from all test invocations across the test suite
- Update docs to reflect opt-in git extension behavior
- Replace TestGitExtensionAutoInstall with TestGitExtensionOptIn tests

BREAKING CHANGE: specify init no longer auto-installs the git extension.
Use `specify extension add git` to install it explicitly.
The --no-git flag has been removed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mnriem mnriem force-pushed the copilot/make-git-extension-opt-in branch from 558bfa9 to 90d1d69 Compare June 5, 2026 20:25
Git functionality is now entirely managed by the git extension.
Core scripts only handle directory-based feature creation and numbering.

- Remove has_git(), check_feature_branch(), git branch creation from core
- Simplify number detection to use only spec directory scanning
- Remove HAS_GIT output from get_feature_paths()
- Remove git remote fetching and branch querying
- Keep BRANCH_NAME output key for backward compatibility

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 5, 2026 23:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 36/36 changed files
  • Comments generated: 6

Comment thread src/specify_cli/commands/init.py
Comment thread src/specify_cli/commands/init.py
Comment thread src/specify_cli/commands/init.py
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread tests/integrations/test_cli.py
mnriem and others added 2 commits June 5, 2026 19:22
- Remove is_git_repo() and init_git_repo() dead code from _utils.py
- Remove --branch-numbering from init command
- Remove git from 'specify check' (now extension-only)
- Update docs: git is optional prerequisite, check command description
- Fix tests to reflect no-git-in-core reality (fallback to main)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… core

Core scripts now resolve feature context exclusively from:
1. SPECIFY_FEATURE env var (set by git extension)
2. .specify/feature.json (persisted by specify command)

Removed find_feature_dir_by_prefix() and directory scanning heuristics —
these are the git extension's responsibility. Scripts error clearly when
no feature context is available.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 6, 2026 01:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 44/44 changed files
  • Comments generated: 8

Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread docs/upgrade.md Outdated
Comment thread docs/upgrade.md Outdated
Comment thread docs/local-development.md Outdated
Comment thread src/specify_cli/commands/init.py
…-options

- specify command template now reads feature_numbering (preferred) with
  fallback to branch_numbering (deprecated) from init-options.json
- Git extension reads git-config.yml > feature_numbering > branch_numbering
- init now writes feature_numbering: sequential to init-options.json
- Deprecation warning emitted when branch_numbering is used as fallback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 8, 2026 15:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 46/46 changed files
  • Comments generated: 8

Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread docs/upgrade.md Outdated
Comment thread docs/local-development.md Outdated
Comment thread src/specify_cli/commands/init.py
When SPECIFY_FEATURE_DIRECTORY is set, get_feature_paths() now writes the
value to .specify/feature.json so future sessions without the env var can
still resolve the feature directory. The write is idempotent — it skips
when the file already contains the same value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Comments suppressed due to low confidence (1)

docs/upgrade.md:285

  • These instructions say setting SPECIFY_FEATURE is sufficient for non-git projects, but the updated shared scripts now require SPECIFY_FEATURE_DIRECTORY or .specify/feature.json to resolve the feature directory. Update the docs to reflect the new required feature context so non-git workflows remain usable.
Projects that do not use Git can still work with Spec Kit by setting `SPECIFY_FEATURE` manually before planning commands:

```bash
# Bash/Zsh
export SPECIFY_FEATURE="001-my-feature"
  • Files reviewed: 46/46 changed files
  • Comments generated: 11

Comment thread src/specify_cli/commands/init.py
Comment thread src/specify_cli/commands/init.py
Comment thread scripts/bash/common.sh
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread scripts/bash/setup-tasks.sh Outdated
Comment thread docs/local-development.md Outdated
mnriem and others added 2 commits June 8, 2026 15:49
- Update error messages in common.sh and common.ps1 to reference
  SPECIFY_FEATURE_DIRECTORY instead of SPECIFY_FEATURE (which no longer
  resolves feature directories)
- Fix get_current_branch comment (returns empty string, not error)
- Update upgrade.md to reference SPECIFY_FEATURE_DIRECTORY with correct
  example paths
- Update local-development.md troubleshooting: replace stale 'Git step
  skipped' row with actionable git extension guidance

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 8, 2026 21:06
@mnriem mnriem force-pushed the copilot/make-git-extension-opt-in branch from a61adfb to 458449a Compare June 8, 2026 21:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 46/46 changed files
  • Comments generated: 3

Comment thread src/specify_cli/commands/init.py
Comment thread scripts/bash/common.sh
Comment thread scripts/powershell/common.ps1 Outdated
- Use json_escape in printf fallback when jq is unavailable (common.sh)
- Replace utf8NoBOM encoding with UTF8Encoding($false) for PowerShell
  5.1 compatibility (common.ps1)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 46/46 changed files
  • Comments generated: 1

Comment thread src/specify_cli/commands/init.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Comments suppressed due to low confidence (2)

scripts/bash/create-new-feature.sh:253

  • create-new-feature.sh now drives feature directory creation without relying on git, but it doesn't persist the resolved feature directory to .specify/feature.json and it still tells users to export SPECIFY_FEATURE. Since get_feature_paths now requires SPECIFY_FEATURE_DIRECTORY or feature.json, a fresh run of this script can leave follow-on scripts (setup-plan/tasks/check-prerequisites) without resolvable feature context unless the user manually sets SPECIFY_FEATURE_DIRECTORY. Persist the feature directory via _persist_feature_json and update the persistence hint accordingly.
    mkdir -p "$FEATURE_DIR"

    if [ ! -f "$SPEC_FILE" ]; then
        TEMPLATE=$(resolve_template "spec-template" "$REPO_ROOT") || true
        if [ -n "$TEMPLATE" ] && [ -f "$TEMPLATE" ]; then

scripts/powershell/create-new-feature.ps1:201

  • create-new-feature.ps1 still only sets SPECIFY_FEATURE after creating the feature directory. With the new common.ps1 behavior, downstream scripts resolve feature context from SPECIFY_FEATURE_DIRECTORY or .specify/feature.json, so a run of this script can leave follow-on commands without resolvable feature context. Persist the feature directory via Save-FeatureJson and set SPECIFY_FEATURE_DIRECTORY for the current session (in addition to SPECIFY_FEATURE if you still want to expose the feature name).
    New-Item -ItemType Directory -Path $featureDir -Force | Out-Null

    if (-not (Test-Path -PathType Leaf $specFile)) {
        $template = Resolve-Template -TemplateName 'spec-template' -RepoRoot $repoRoot
        if ($template -and (Test-Path $template)) {
  • Files reviewed: 46/46 changed files
  • Comments generated: 0 new

@mnriem mnriem changed the title feat(init)!: make git extension opt-in and remove --no-git at v0.10.0 feat: make git extension opt-in and remove --no-git at v0.10.0 Jun 8, 2026
…ions

These guards are no longer needed since the branch-name validation they
protected against has been removed from check-prerequisites.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Comments suppressed due to low confidence (1)

tests/integrations/test_integration_subcommand.py:967

  • These assertions expect setup-tasks.sh to contain hard-coded /speckit-plan and then change to /speckit.plan after an integration switch. The shared bash scripts now build command hints dynamically via format_speckit_command + integration.json (and do not contain literal /speckit-* strings), so this test will fail even when behavior is correct. Update the test to assert the dynamic formatter is present (and no hard-coded invocations exist), or validate command-style changes via rendered templates (which do use __SPECKIT_COMMAND_*__ placeholders).
  • Files reviewed: 46/46 changed files
  • Comments generated: 4

Comment on lines 239 to +243
if [ "$DRY_RUN" != true ]; then
if [ "$HAS_GIT" = true ]; then
branch_create_error=""
if ! branch_create_error=$(git checkout -q -b "$BRANCH_NAME" 2>&1); then
current_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
# Check if branch already exists
if git branch --list "$BRANCH_NAME" | grep -q .; then
if [ "$ALLOW_EXISTING" = true ]; then
# If we're already on the branch, continue without another checkout.
if [ "$current_branch" = "$BRANCH_NAME" ]; then
:
# Otherwise switch to the existing branch instead of failing.
elif ! switch_branch_error=$(git checkout -q "$BRANCH_NAME" 2>&1); then
>&2 echo "Error: Failed to switch to existing branch '$BRANCH_NAME'. Please resolve any local changes or conflicts and try again."
if [ -n "$switch_branch_error" ]; then
>&2 printf '%s\n' "$switch_branch_error"
fi
exit 1
fi
elif [ "$USE_TIMESTAMP" = true ]; then
>&2 echo "Error: Branch '$BRANCH_NAME' already exists. Rerun to get a new timestamp or use a different --short-name."
exit 1
else
>&2 echo "Error: Branch '$BRANCH_NAME' already exists. Please use a different feature name or specify a different number with --number."
exit 1
fi
else
>&2 echo "Error: Failed to create git branch '$BRANCH_NAME'."
if [ -n "$branch_create_error" ]; then
>&2 printf '%s\n' "$branch_create_error"
else
>&2 echo "Please check your git configuration and try again."
fi
exit 1
fi
if [ -d "$FEATURE_DIR" ] && [ "$ALLOW_EXISTING" != true ]; then
if [ "$USE_TIMESTAMP" = true ]; then
>&2 echo "Error: Feature directory '$FEATURE_DIR' already exists. Rerun to get a new timestamp or use a different --short-name."
else
exit 1
}

New-Item -ItemType Directory -Path $featureDir -Force | Out-Null
Comment thread scripts/powershell/common.ps1 Outdated
Comment on lines 63 to 67
# Strip repo root prefix if the value is absolute and under repo root
$prefix = $RepoRoot + [System.IO.Path]::DirectorySeparatorChar
if ($FeatureDirectory.StartsWith($prefix, [System.StringComparison]::OrdinalIgnoreCase)) {
$FeatureDirectory = $FeatureDirectory.Substring($prefix.Length)
}
Comment thread scripts/bash/setup-tasks.sh Outdated
@@ -28,11 +28,6 @@ eval "$_paths_output"
unset _paths_output

# Validate branch
mnriem and others added 2 commits June 8, 2026 17:49
…anch

The git extension's script only creates the git branch — rename it to
reflect that responsibility. The core create-new-feature.sh/.ps1 handles
feature directory creation and feature.json persistence.

Also includes fixes from review feedback:
- common.sh: _persist_feature_json uses json_escape fallback
- common.ps1: Save-FeatureJson uses UTF8Encoding for PS 5.1 compat
- common.ps1: case-sensitive path stripping on non-Windows
- create-new-feature.sh/ps1: output both SPECIFY_FEATURE and
  SPECIFY_FEATURE_DIRECTORY
- setup-tasks.sh: fix stale 'Validate branch' comment

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants