Skip to content

Commit 927f54f

Browse files
CopilotmnriemCopilot
authored
feat: make git extension opt-in and remove --no-git at v0.10.0 (#2873)
* feat(init)!: make git extension opt-in and remove --no-git at v0.10.0 - 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> * refactor(scripts): remove git operations from core scripts 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> * refactor: remove all git operations from core - 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> * refactor(scripts): remove directory scanning and branch fallback from 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> * feat: introduce feature_numbering, deprecate branch_numbering in init-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> * fix: remove trailing whitespace in common.ps1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(scripts): persist SPECIFY_FEATURE_DIRECTORY env var to feature.json 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> * fix: address review feedback — error messages and docs - 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> * fix(scripts): harden feature.json persistence - 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> * refactor(scripts): remove dead feature_json_matches_feature_dir functions 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> * refactor(git-ext): rename create-new-feature to create-new-feature-branch 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> * fix(tests): update references to renamed git extension scripts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(tests): remove duplicate EXT_CREATE_FEATURE assignments Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 90832d1 commit 927f54f

50 files changed

Lines changed: 538 additions & 1627 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Codebuddy CLI](https://www.codebuddy.ai/cli), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Pi Coding Agent](https://pi.dev)
77
- [uv](https://docs.astral.sh/uv/) for package management (recommended) or [pipx](https://pipx.pypa.io/) for persistent installation
88
- [Python 3.11+](https://www.python.org/downloads/)
9-
- [Git](https://git-scm.com/downloads)
9+
- [Git](https://git-scm.com/downloads) _(optional — required only when the git extension is enabled)_
1010

1111
## Installation
1212

docs/local-development.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ rm -rf .venv dist build *.egg-info
162162
|---------|-----|
163163
| `ModuleNotFoundError: typer` | Run `uv pip install -e .` |
164164
| Scripts not executable (Linux) | Re-run init or `chmod +x scripts/*.sh` |
165-
| Git step skipped | You passed `--no-git` or Git not installed |
165+
| Git commands unavailable | Install the git extension with `specify extension add git` |
166166
| Wrong script type downloaded | Pass `--script sh` or `--script ps` explicitly |
167167
| TLS errors on corporate network | Configure your environment's certificate store or proxy. The `--skip-tls` flag is deprecated and has no effect. |
168168

docs/reference/core.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,13 @@ specify init [<project_name>]
1515
| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) |
1616
| `--here` | Initialize in the current directory instead of creating a new one |
1717
| `--force` | Force merge/overwrite when initializing in an existing directory |
18-
| `--no-git` | Skip git repository initialization |
1918
| `--ignore-agent-tools` | Skip checks for AI coding agent CLI tools |
2019
| `--preset <id>` | Install a preset during initialization |
21-
| `--branch-numbering` | Branch numbering strategy: `sequential` (default) or `timestamp` |
2220

2321
Creates a new Spec Kit project with the necessary directory structure, templates, scripts, and AI coding agent integration files.
2422

2523
> [!NOTE]
26-
> The git extension is currently enabled by default during `specify init`.
27-
> Starting in `v0.10.0`, it will require explicit opt-in. To add it after init, run `specify extension add git`.
24+
> Git repository initialization and branching are managed by the **git extension**, which is not installed by default. Run `specify extension add git` after init to enable git workflows.
2825
2926
Use `<project_name>` to create a new directory, or `--here` (or `.`) to initialize in the current directory. If the directory already has files, use `--force` to merge without confirmation.
3027

@@ -45,14 +42,8 @@ specify init --here --force --integration copilot
4542
# Use PowerShell scripts (Windows/cross-platform)
4643
specify init my-project --integration copilot --script ps
4744

48-
# Skip git initialization
49-
specify init my-project --integration copilot --no-git
50-
5145
# Install a preset during initialization
5246
specify init my-project --integration copilot --preset compliance
53-
54-
# Use timestamp-based branch numbering (useful for distributed teams)
55-
specify init my-project --integration copilot --branch-numbering timestamp
5647
```
5748

5849
### Environment Variables
@@ -67,7 +58,7 @@ specify init my-project --integration copilot --branch-numbering timestamp
6758
specify check
6859
```
6960

70-
Checks that required tools are available on your system: `git` and any CLI-based AI coding agents. IDE-based agents are skipped since they don't require a CLI tool.
61+
Checks that CLI-based AI coding agents are available on your system. IDE-based agents are skipped since they don't require a CLI tool.
7162

7263
This command stays offline. If a command behaves like an older Spec Kit version or an expected CLI feature is missing, run `specify self check` to check whether your local CLI is behind the latest release.
7364

docs/upgrade.md

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -257,70 +257,38 @@ rm speckit.old-command-name.md
257257
# Restart your IDE
258258
```
259259

260-
### Scenario 4: "I'm working on a project without Git"
260+
### Scenario 4: "I don't want the git extension"
261261

262-
If you initialized your project with `--no-git`, you can still upgrade:
262+
The git extension is now opt-in, so upgrades do not install it unless you add it explicitly.
263263

264264
```bash
265265
# Manually back up files you customized
266-
cp .specify/memory/constitution.md /tmp/constitution-backup.md
266+
cp .specify/memory/constitution.md .specify/memory/constitution.backup.md
267267

268268
# Run upgrade
269-
specify init --here --force --integration copilot --no-git
269+
specify init --here --force --integration copilot
270270

271271
# Restore customizations
272-
mv /tmp/constitution-backup.md .specify/memory/constitution.md
272+
mv .specify/memory/constitution.backup.md .specify/memory/constitution.md
273273
```
274274

275-
The `--no-git` flag skips git initialization but doesn't affect file updates.
276-
277-
---
278-
279-
## Using `--no-git` Flag
280-
281-
The `--no-git` flag tells Spec Kit to **skip git repository initialization**. This is useful when:
282-
283-
- You manage version control differently (Mercurial, SVN, etc.)
284-
- Your project is part of a larger monorepo with existing git setup
285-
- You're experimenting and don't want version control yet
286-
287-
**During initial setup:**
275+
If you later decide you want the git extension's commands and hooks, install it explicitly:
288276

289277
```bash
290-
specify init my-project --integration copilot --no-git
278+
specify extension add git
291279
```
292280

293-
**During upgrade:**
294-
295-
```bash
296-
specify init --here --force --integration copilot --no-git
297-
```
298-
299-
### What `--no-git` does NOT do
300-
301-
❌ Does NOT prevent file updates
302-
❌ Does NOT skip slash command installation
303-
❌ Does NOT affect template merging
304-
305-
It **only** skips running `git init` and creating the initial commit.
306-
307-
### Working without Git
308-
309-
If you use `--no-git`, you'll need to manage feature directories manually:
310-
311-
**Set the `SPECIFY_FEATURE` environment variable** before using planning commands:
281+
Projects that do not use Git can still work with Spec Kit by setting `SPECIFY_FEATURE_DIRECTORY` to the feature directory path before planning commands:
312282

313283
```bash
314284
# Bash/Zsh
315-
export SPECIFY_FEATURE="001-my-feature"
285+
export SPECIFY_FEATURE_DIRECTORY="specs/001-my-feature"
316286

317287
# PowerShell
318-
$env:SPECIFY_FEATURE = "001-my-feature"
288+
$env:SPECIFY_FEATURE_DIRECTORY = "specs/001-my-feature"
319289
```
320290

321-
This tells Spec Kit which feature directory to use when creating specs, plans, and tasks.
322-
323-
**Why this matters:** Without git, Spec Kit can't detect your current branch name to determine the active feature. The environment variable provides that context manually.
291+
Alternatively, run the `/speckit.specify` command which creates `.specify/feature.json` automatically.
324292

325293
---
326294

extensions/git/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ When Git is not installed or the directory is not a Git repository:
9494

9595
The extension bundles cross-platform scripts:
9696

97-
- `scripts/bash/create-new-feature.sh` — Bash implementation
97+
- `scripts/bash/create-new-feature-branch.sh` — Bash implementation (branch creation only)
9898
- `scripts/bash/git-common.sh` — Shared Git utilities (Bash)
99-
- `scripts/powershell/create-new-feature.ps1` — PowerShell implementation
99+
- `scripts/powershell/create-new-feature-branch.ps1` — PowerShell implementation (branch creation only)
100100
- `scripts/powershell/git-common.ps1` — Shared Git utilities (PowerShell)

extensions/git/commands/speckit.git.feature.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ If the user explicitly provided `GIT_BRANCH_NAME` (e.g., via environment variabl
3131
Determine the branch numbering strategy by checking configuration in this order:
3232

3333
1. Check `.specify/extensions/git/git-config.yml` for `branch_numbering` value
34-
2. Check `.specify/init-options.json` for `branch_numbering` value (backward compatibility)
35-
3. Default to `sequential` if neither exists
34+
2. Check `.specify/init-options.json` for `feature_numbering` value (inherit from core)
35+
3. Check `.specify/init-options.json` for `branch_numbering` value (deprecated, backward compatibility — will be removed in a future release)
36+
4. Default to `sequential` if none of the above exist
3637

3738
## Execution
3839

@@ -43,10 +44,10 @@ Generate a concise short name (2-4 words) for the branch:
4344

4445
Run the appropriate script based on your platform:
4546

46-
- **Bash**: `.specify/extensions/git/scripts/bash/create-new-feature.sh --json --short-name "<short-name>" "<feature description>"`
47-
- **Bash (timestamp)**: `.specify/extensions/git/scripts/bash/create-new-feature.sh --json --timestamp --short-name "<short-name>" "<feature description>"`
48-
- **PowerShell**: `.specify/extensions/git/scripts/powershell/create-new-feature.ps1 -Json -ShortName "<short-name>" "<feature description>"`
49-
- **PowerShell (timestamp)**: `.specify/extensions/git/scripts/powershell/create-new-feature.ps1 -Json -Timestamp -ShortName "<short-name>" "<feature description>"`
47+
- **Bash**: `.specify/extensions/git/scripts/bash/create-new-feature-branch.sh --json --short-name "<short-name>" "<feature description>"`
48+
- **Bash (timestamp)**: `.specify/extensions/git/scripts/bash/create-new-feature-branch.sh --json --timestamp --short-name "<short-name>" "<feature description>"`
49+
- **PowerShell**: `.specify/extensions/git/scripts/powershell/create-new-feature-branch.ps1 -Json -ShortName "<short-name>" "<feature description>"`
50+
- **PowerShell (timestamp)**: `.specify/extensions/git/scripts/powershell/create-new-feature-branch.ps1 -Json -Timestamp -ShortName "<short-name>" "<feature description>"`
5051

5152
**IMPORTANT**:
5253
- Do NOT pass `--number` — the script determines the correct next number automatically

extensions/git/scripts/bash/create-new-feature.sh renamed to extensions/git/scripts/bash/create-new-feature-branch.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env bash
2-
# Git extension: create-new-feature.sh
3-
# Adapted from core scripts/bash/create-new-feature.sh for extension layout.
2+
# Git extension: create-new-feature-branch.sh
3+
# Creates a git feature branch only. The feature directory and spec file
4+
# are created by the core create-new-feature.sh script.
45
# Sources common.sh from the project's installed scripts, falling back to
56
# git-common.sh for minimal git helpers.
67

extensions/git/scripts/powershell/create-new-feature.ps1 renamed to extensions/git/scripts/powershell/create-new-feature-branch.ps1

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env pwsh
2-
# Git extension: create-new-feature.ps1
3-
# Adapted from core scripts/powershell/create-new-feature.ps1 for extension layout.
2+
# Git extension: create-new-feature-branch.ps1
3+
# Creates a git feature branch only. The feature directory and spec file
4+
# are created by the core create-new-feature.ps1 script.
45
# Sources common.ps1 from the project's installed scripts, falling back to
56
# git-common.ps1 for minimal git helpers.
67
[CmdletBinding()]
@@ -19,7 +20,7 @@ param(
1920
$ErrorActionPreference = 'Stop'
2021

2122
if ($Help) {
22-
Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
23+
Write-Host "Usage: ./create-new-feature-branch.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
2324
Write-Host ""
2425
Write-Host "Options:"
2526
Write-Host " -Json Output in JSON format"
@@ -37,7 +38,7 @@ if ($Help) {
3738
}
3839

3940
if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) {
40-
Write-Error "Usage: ./create-new-feature.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
41+
Write-Error "Usage: ./create-new-feature-branch.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
4142
exit 1
4243
}
4344

scripts/bash/check-prerequisites.sh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ if $PATHS_ONLY; then
111111
exit 0
112112
fi
113113

114-
# Validate branch name
115-
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
116-
117114
# Validate required directories and files
118115
if [[ ! -d "$FEATURE_DIR" ]]; then
119116
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2

0 commit comments

Comments
 (0)