Skip to content

Git 2.55.0.windows.3: writes to refs/remotes/* silently rolled back on machines with antivirus real-time protection (exit 0, no output) #6396

Description

@XLF66666

Existing issues matching what you're seeing

  • I was not able to find an open or closed issue matching what I'm seeing

Git for Windows version

git version 2.55.0.windows.3
cpu: x86_64
built from commit: 52ca1113d651127f89477a8763f86ab20f645e1d
sizeof-long: 4
sizeof-size_t: 8
shell-path: D:/git-sdk-64/usr/bin/sh
rust: disabled
feature: fsmonitor--daemon
gettext: enabled
libcurl: 8.21.0
OpenSSL: OpenSSL 3.5.7 9 Jun 2026
zlib: 1.3.2
SHA-1: SHA1_DC
SHA-256: SHA256_BLK
default-ref-format: files
default-hash: sha1

Windows version

Windows 11

Windows CPU architecture

x86_64 (64-bit)

Additional Windows version information

Microsoft Windows [版本 10.0.26100.4652]

Options set during installation

Portable/bundled copy — NOT installed via Git for Windows setup.exe. It is shipped by WorkBuddy desktop v5.3.14 at ~/.workbuddy/binaries/PortableGit/versions/1.2.0/ (so no C:\Program Files\Git\etc\install-options.txt exists on this machine). Default options otherwise. The only effective non-default is that this git.exe sits ahead of system Git on PATH inside the WorkBuddy agent session.

Other interesting things

Environment correlation (the key signal):

  • Affected binary: bundled portable Git 2.55.0.windows.3 (path above) → refs/remotes/* writes silently lost.
  • Control: system-installed Git 2.45.2.windows.1 (C:\Program Files\Git) on the SAME machine, SAME repo, SAME operations → works correctly.
  • Resident security software: Windows Defender real-time protection enabled + Sangfor aTrust zero-trust client.

Scope of the defect (what still works) — isolated via a systematic experiment matrix:

Operation Result
Write to refs/remotes/* (fetch/push/update-ref) silently lost
Write to refs/heads/* (local branches) works
Write objects (git hash-object -w) works
Write .git/config (git config) works
Read-only commands (status/rev-parse/log/branch) work, do not trigger cleanup
Plain bash-level printf > .git/refs/remotes/origin/master persists (survives 60s polling)
Manual writes via Git 2.45.2 update-ref persists

Excluded causes: non-sample hooks (none), core.hooksPath (unset), fsmonitor/maintenance (unset), reftable (absent), commondir (absent), repo corruption (reproduces on a fresh empty repo under pure-ASCII $env:TEMP), binary tampering (valid Johannes Schindelin Authenticode signature), path-based or process-based sandboxing (failure follows the binary when copied to a plain directory, and reproduces in native PowerShell with no shell wrappers).

Hypothesis: The ref-write transaction path in 2.55 interacts badly with real-time file-system filter drivers (antivirus / zero-trust clients hooking file I/O): the write is reported complete (exit 0, no stderr), then silently rolled back after the file handle closes. The 2.45 code path does not trigger this. Could not identify the specific filter (querying Defender exclusions needs admin), but the binary-version correlation is deterministic on this machine. This resembles a previously-fixed git-for-windows class of bug where a security-software Windows Filter Platform driver rewrote git's stdout buffering and output was lost on exit (fixed via explicit fflush(stdout) before exit) — same root category (resident security filter driver silently breaking git I/O on Windows), 2.55 regressed where 2.45 did not.

Impact: remote-tracking refs silently regress to a stale packed-refs snapshot, so every consumer of "where does origin point" gets wrong data: git status shows a bogus ahead/behind count, and AI coding agents relying on these refs to decide whether to pull can skip syncs or act on stale remote history — with zero error signal.

Workaround: writing the loose ref file directly (outside git) persists:
mkdir -p .git/refs/remotes/origin
git ls-remote origin master | awk '{print $1}' > .git/refs/remotes/origin/master

Terminal/shell

PowerShell (native, no shell wrappers). Also reproduces via a plain printf to the ref file in bash, proving it is not shell-specific. The bug manifests ONLY with the bundled 2.55.0.windows.3 binary; system Git 2.45.2.windows.1 on the same machine does NOT exhibit it.

Commands that trigger the issue

$git = "$env:USERPROFILE\.workbuddy\binaries\PortableGit\versions\1.2.0\mingw64\bin\git.exe"
$t = "$env:TEMP\git-refs-bug-repro"
Remove-Item -Recurse -Force $t -ErrorAction SilentlyContinue
New-Item -ItemType Directory $t | Out-Null
Set-Location $t
& $git init -q .
& $git -c user.email=t@t -c user.name=t commit -q --allow-empty -m init
$sha = (& $git rev-parse HEAD).Trim()
& $git update-ref refs/remotes/origin/master $sha
"exit code          : $LASTEXITCODE"
"ref file persisted : $(Test-Path "$t\.git\refs\remotes\origin\master")"
"git reads it back  : $(& $git rev-parse refs/remotes/origin/master 2>$null)"

Expected behaviour

On a healthy setup the three printed lines are:
exit code : 0
ref file persisted : True
git reads it back :
The ref file should persist on disk and git rev-parse refs/remotes/origin/master should return that SHA.

Actual behaviour

On the affected machine the three printed lines are:
exit code : 0 ← success illusion, no error anywhere
ref file persisted : False ← .git/refs/remotes/origin/master does NOT exist on disk
git reads it back : (empty) ← git rev-parse reports "unknown revision"
Additionally, any pre-existing loose refs under .git/refs/remotes/origin/ are DELETED by the operation, so ref resolution falls back to a stale packed-refs snapshot. git status then shows a bogus "[ahead 498]" count. The exact same script with system Git 2.45.2.windows.1 prints True / — same machine, same repo, only the binary differs.

Repository

N/A — reproduces on a freshly git init empty repo under $env:TEMP; not tied to any specific remote or repo contents. (In production the symptom surfaced against a Gitee-hosted project, but the ref-write failure is independent of the remote.)

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions