Skip to content

[Bug]: Window focus runs git fetch even with Git fetch interval set to 0 #13235

Description

@Cybertron1

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Steps to reproduce

  1. Use a repo whose origin is an SSH remote, with keys held by a GUI SSH agent that asks for approval on every use (1Password SSH agent).
  2. Settings → Source Control → set Git fetch interval to 0.
  3. Open a thread in that repo.
  4. Switch to another app, wait more than 15s, switch back to T3 Code.

Expected behavior

No git fetch runs, and the SSH agent never prompts.
The setting's help text says: "Set to 0 to avoid automatic Git prompts."

Actual behavior

Each time the window regains focus or becomes visible, T3 Code runs git fetch --quiet --no-tags <remote>, and 1Password prompts for key approval.

Why it happens:

Only the periodic loop checks automaticGitFetchInterval: VcsStatusBroadcaster.ts#L558.
refreshStatus does not, and every caller of it fetches, including the post-mutation refreshGitStatus calls in ws.ts and the worktree branch rename in ProviderCommandReactor.

Suggested fix: in refreshStatus, read automaticGitFetchInterval and pass refreshUpstream: false when it is zero.
An explicit user action like Pull or Push can still fetch.

Related: #1190, #1467 (same symptom, both closed when the interval setting landed in #2605).

Impact: Minor bug or occasional failure. It's disruptive, though: an approval prompt steals focus every time I switch back to the app.

Version or commit: main @ f5ef0dd

Environment: Windows 11 + WSL2 (Linux 6.18), git 2.55.0, core.sshCommand=/mnt/c/Windows/System32/OpenSSH/ssh.exe, 1Password SSH agent.

Suggested fix: in refreshStatus, read automaticGitFetchInterval and pass refreshUpstream: false when it is zero.
An explicit user action like Pull or Push can still fetch.

Related: #1190, #1467 (same symptom, both closed when the interval setting landed in #2605).

Impact

Cosmetic issue

Version or commit

main @ f5ef0dd

Environment

Windows 11 + WSL2 (Linux 6.18), git 2.55.0, core.sshCommand=/mnt/c/Windows/System32/OpenSSH/ssh.exe, 1Password SSH agent.

Logs or stack traces

Screenshots, recordings, or supporting files

No response

Workaround

Fetch over HTTPS and push over SSH, so background fetches don't touch the SSH agent:

git remote set-url origin https://<host>/<repo>.git
git remote set-url --push origin git@<host>:<repo>.git

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 23, 2026
  2. juliusmarminge commented on Sep 23, 2026

    @juliusmarminge
    Member

    Triage

    Confirmed on main at f5ef0ddb (the commit in the report). Setting Git fetch interval to 0 disables only the periodic remote poller. Focusing the window, or making it visible again, still starts git fetch --quiet --no-tags <remote>.

    The setting copy promises that 0 avoids automatic Git prompts (SourceControlSettings.tsx). The poller honors that: streamStatus passes refreshUpstream: !Duration.isZero(configuredInterval), and with a zero interval the initial status read does not fetch. VcsStatusBroadcaster.refreshStatus does not. It always calls workflow.remoteStatus({ cwd }) with no refreshUpstream: false, after invalidateStatus. statusDetailsRemote then calls refreshStatusUpstreamIfStale, which runs:

    git --git-dir <common-dir> fetch --quiet --no-tags <remote>

    That matches the command in the report. Successful fetches are cached for 15 seconds (STATUS_UPSTREAM_REFRESH_INTERVAL); failures back off from 30 seconds. Because a zero interval never fills that cache from the poller, the first refocus fetches immediately, and another refocus after the cache expires fetches again. The focus and visibilitychange listeners in GitActionsControl debounce into one vcs.refreshStatus call. Opening the Git actions menu uses that same RPC. The fetch is capped at 5 seconds and sets SSH_ASKPASS_REQUIRE=never, which blocks OpenSSH askpass dialogs but not a 1Password (or other) SSH agent hooked up through core.sshCommand.

    refreshStatus is also used after git mutations (refreshGitStatus in ws.ts), after an automatic worktree branch rename, and when the mobile client selects a thread. A zero interval should skip the fetch on those paths too. Explicit pull, push, and fetch still go through their own git commands, so they can keep prompting. The battery-saver background preset sets this interval to 0 by default, so those users hit the same focus fetch without changing the number field.

    This is the gap left by #2605, which closed #1190 and #1467. That change gated the poller and added the askpass guard; it did not gate refreshStatus. No open issue covers this focus path.

    The suggested fix is the right one: when automaticGitFetchInterval is zero, refreshStatus should pass refreshUpstream: false. Local status and an explicit Pull or Push stay intact. The HTTPS-fetch / SSH-push remote URL split is a valid workaround until then.

  3. added
    acceptedfeature request accepted
    via-triageFiled through npx t3 triage
    and removed
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 23, 2026
  4. arnaud-dezandee commented on Oct 9, 2026

    @arnaud-dezandee

    The same fetch path also affects hardware-backed SSH keys with default settings (Git fetch interval 30s), not only at interval 0.

    Setup: GitHub SSH remote, key served by gpg-agent from a YubiKey (IdentityAgent ~/.gnupg/S.gpg-agent.ssh), so every use needs a touch.

    1. In a worktree thread, run Commit, push & PR.
    2. Leave the thread open.

    Before the push, the branch has no upstream, so resolveCurrentUpstream returns null and nothing is fetched. The push sets an upstream, and from then on status reads run git fetch --quiet --no-tags --no-auto-gc <remote> through refreshStatusUpstreamIfStale. Each fetch asks the YubiKey for a touch:

    • Touching makes the fetch succeed, which keeps the 15s refresh cache (STATUS_UPSTREAM_REFRESH_INTERVAL) cycling, so the prompts continue for as long as the thread is open.
    • Ignoring the prompt hits the 5s timeout and backs off (30s, doubling up to 15m), so the prompts slow down but never stop.

    As in #11930, STATUS_UPSTREAM_REFRESH_ENV only covers askpass and terminal prompts, so agent-side prompts get through.

    Workaround that keeps ahead/behind counts working: fetch over HTTPS (gh credential helper) and push over SSH.

    [url "https://github.com/"]
    	insteadOf = git@github.com:
    [url "git@github.com:"]
    	pushInsteadOf = git@github.com:
    	pushInsteadOf = https://github.com/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions