Skip to content

fix(git): stop the feature-branch fetch from blocking on a credential prompt - #5213

Open
xizhilanre wants to merge 3 commits into
github:mainfrom
xizhilanre:fix/5199-git-fetch-prompt-guard
Open

xizhilanre wants to merge 3 commits into
github:mainfrom
xizhilanre:fix/5199-git-fetch-prompt-guard

Conversation

@xizhilanre

Copy link
Copy Markdown

Problem

speckit.git.feature runs as the mandatory before_specify hook, and its feature-branch scripts run git fetch --all --prune for non-dry-run invocations. When a remote is HTTPS and has no usable credential helper, git writes Username for 'https://…': to the tty — the output redirect does not hide it — and waits for input. /speckit.specify then appears to hang.

The dry-run path already guards git ls-remote with GIT_TERMINAL_PROMPT=0; the real fetch path did not, in any of the three twins.

Root cause

Each implementation called the fetch without the guard:

file before
extensions/git/scripts/bash/create-new-feature-branch.sh git fetch --all --prune >/dev/null 2>&1 || true
extensions/git/scripts/powershell/create-new-feature-branch.ps1 git fetch --all --prune 2>$null | Out-Null
extensions/git/scripts/python/create_new_feature_branch.py subprocess.run(["git", "fetch", "--all", "--prune"], …) with no env

Change

Apply the same GIT_TERMINAL_PROMPT=0 guard the dry-run path uses, in all three twins, so the fetch fails fast and || true / catch / nothing-to-check continues:

  • bash: GIT_TERMINAL_PROMPT=0 git fetch --all --prune >/dev/null 2>&1 || true
  • PowerShell: set $env:GIT_TERMINAL_PROMPT = '0' around the fetch, restore to $null afterwards (the same idiom already used for git ls-remote in the same file)
  • Python: env={**os.environ, "GIT_TERMINAL_PROMPT": "0"}

Verification

New tests/test_git_fetch_prompt_guard.py (3 tests, one per implementation). Each registers a git shim that records GIT_TERMINAL_PROMPT when fetch is invoked and passes every other call through to the real git, then drives the real script and asserts the recorded value is 0.

uv run python -m pytest tests/test_git_fetch_prompt_guard.py -q

with the fix:                        2 passed, 1 skipped
with extensions/git/scripts reverted: 2 failed, 1 skipped

The Python and PowerShell tests fail without the change with AssertionError: assert '' == '0' — the guard was absent, which is the regression this pins. The bash test is skipped on this Windows host (only the WSL bash launcher is installed, which tests/conftest.requires_bash rejects); it runs on the Linux CI.

Related suites, same command, before vs after (the 25 remaining failures/errors are pre-existing on this host — no native bash, no PS 5.1 harness setup — and are identical on the unmodified main tree):

uv run python -m pytest tests/test_git_fetch_prompt_guard.py tests/test_timestamp_branches.py tests/test_init_dir.py -q
before: 27 failed, 18 passed, 73 skipped
after:  25 failed, 20 passed, 73 skipped

The two-test delta is exactly the new regression tests flipping from fail to pass.

Windows PowerShell 5.1 evidence

The PowerShell twin was exercised under Windows PowerShell 5.1.22621.4391 (dot-sourced with a git function shim, in an ASCII-path temp checkout):

PS> powershell.exe -NoProfile -ExecutionPolicy Bypass -File h.ps1
BRANCH_NAME: 001-probe-ps51
FEATURE_NUM: 001
# recorded GIT_TERMINAL_PROMPT at fetch = '0'

Only PS 5.1 constructs are used (try/catch, $env: assignment).

Lint

uvx ruff@0.15.0 check src tests   # the CI command

passes for the changed test file; the extension scripts are outside that CI gate.

AI disclosure

Implemented with DeepSeek Harness (agent) using model deepseek-v4.1-flash, running autonomously. Extent: code generation for the three guard lines and the regression tests, plus running the test evidence above. The submitting account holder reviewed the diff and is the one responding to review.

Closes #5199

… prompt (github#5199)

check_existing_branches runs `git fetch --all --prune` for non-dry-run
invocations without `GIT_TERMINAL_PROMPT=0`. When a remote is HTTPS and has
no usable credential helper, git prompts on the tty, and because
`speckit.git.feature` runs as the mandatory `before_specify` hook,
`/speckit.specify` blocks instead of continuing.

The dry-run path already passes the guard to `git ls-remote`; the real fetch
path did not, in any of the three twins. Apply the same guard to bash,
PowerShell and Python so the fetch fails fast and the script continues.

Refs github#5199

Assisted-by: DeepSeek Harness (model: deepseek-v4.1-flash, autonomous)

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.

🟡 Changes recommended

A critical release-delivery issue remains because the bundled script changes are not accompanied by the required extension manifest and catalog version bump, so existing installations will not receive the fix.

1 open issue
What changed in this PR

This pull request prevents Git feature-branch fetches from blocking on HTTPS credential prompts by disabling terminal prompting across Bash, PowerShell, and Python implementations. It also adds regression tests for the guard.

Changes:

  • Sets GIT_TERMINAL_PROMPT=0 for non-dry-run fetches in all three script variants.
  • Adds coverage verifying the environment variable during fetch operations.
  • Requires a synchronized extension version bump in extension.yml and extensions/catalog.json.
  • Requires the PowerShell test to fall back to Windows PowerShell 5.1 when pwsh is unavailable.

This pull request requires changes.

File Description
tests/​test_git_fetch_prompt_guard.py Adds regression tests for Python, Bash, and PowerShell, but currently skips the PowerShell path on supported Windows hosts that only provide Windows PowerShell 5.1.
extensions/​git/​scripts/​python/​create_new_feature_branch.py Passes GIT_TERMINAL_PROMPT=0 to the fetch subprocess.
extensions/​git/​scripts/​powershell/​create-new-feature-branch.ps1 Temporarily disables terminal prompts around the PowerShell fetch.
extensions/​git/​scripts/​bash/​create-new-feature-branch.sh Disables terminal prompts for the Bash fetch; the bundled extension version metadata must also be bumped for this content change to be released.

Review effort: Lite (auto)

# The dry-run path already sets this for `git ls-remote`. Without it,
# an HTTPS remote with no usable credential helper makes git prompt on
# the tty, and /speckit.specify hangs instead of continuing.
GIT_TERMINAL_PROMPT=0 git fetch --all --prune >/dev/null 2>&1 || true
…rd (github#5199)

The version-bump gate rejects content changes under `extensions/git/`
without a manifest bump, because installed copies only receive updates when
`extension.version` increases. Bump `extension.yml` and the matching
`catalog.json` entry from 1.0.1 to 1.0.2, and drop the stray blank line at
the end of the new regression test (`git diff --check`).

Assisted-by: DeepSeek Harness (model: deepseek-v4.1-flash, autonomous)
The extension scripts resolve their project root from their own location, so
the bash and PowerShell cases ran the checkout's copy and created feature
branches in this repository while testing. Install the scripts into the temp
project's `.specify/scripts` and run those copies instead, so the branch is
created there.

Verified: `git branch --list` is unchanged across the run (2 before, 2
after), 2 passed / 1 skipped on Windows (no native bash; the bash case runs on
Linux CI).

Assisted-by: DeepSeek Harness (model: deepseek-v4.1-flash, autonomous)
@mnriem mnriem added the triage-must-have Verdict: high-value, important work for Spec Kit — do first label Nov 2, 2026
@mnriem
mnriem requested an auto review from Copilot November 2, 2026 18:01

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.

🟡 Changes recommended

The manifest version bump leaves the bundled Git extension test asserting the old version, creating an active critical test failure that must be fixed.

2 open issues

Review effort: Lite (auto)

id: git
name: "Git Branching Workflow"
version: "1.0.1"
version: "1.0.2"
@mnriem

mnriem commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback, resolve conflicts and address test & lint errors

@mnriem mnriem added the author-awaiting Waiting on author response label Nov 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-awaiting Waiting on author response triage-must-have Verdict: high-value, important work for Spec Kit — do first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: git extension: non-dry-run git fetch can block /speckit.specify on a hidden credential prompt

3 participants