Skip to content

Bind-mode git ops fail with phantom "local changes would be overwritten" over virtiofs — inject core.checkStat=minimal #401

Description

@schmitthub

Summary

In a bind-mode container (Docker Desktop on macOS, virtiofs/gRPC-FUSE), git rebase (and checkout/merge/stash pop) intermittently aborts with:

error: Your local changes to the following files would be overwritten by merge:
	<files that differ between the branch and the rebase target>
Please commit your changes or stash them before you merge.
Aborting

…even though git status and git diff report the worktree clean. Not a real conflict, not pre-commit.

Root cause

git's default core.checkStat=normal compares all stat fields (ino, ctime, uid, gid, mtime, size). The clawker bind workspace crosses the macOS host → container boundary over virtiofs, which synthesizes/remaps ino + ctime, and the container claude UID ≠ host UID (the known "virtiofs masks UID/GID" behavior). The git index's recorded stat no longer matches what the container reads, so git flags every file that differs between the branch and the rebase onto as phantom stat-dirty. git status masks this (it re-hashes content → reports clean), but rebase's verify_uptodate refuses to overwrite "modified" files and aborts before the content re-hash.

Intermittent because it only triggers on operations doing verify_uptodate without a prior content re-hash, and only after stat drift accumulates (host-side git ops, container restarts).

Evidence (decisive: stat, not content)

$ git diff               # empty throughout
$ git rebase main        # fails: "local changes would be overwritten"
$ git -c core.checkStat=minimal rebase main
Successfully rebased and updated refs/heads/<branch>.

core.checkStat=minimal compares only mtime+size — the fields virtiofs keeps stable — so the phantom-dirty disappears. Host-side rebase also works (native APFS, stable stat, matching UID).

Proposed fix

clawker already injects git config via GIT_CONFIG_COUNT / GIT_CONFIG_KEY_n / GIT_CONFIG_VALUE_n env vars in internal/docker/env.go (currently for gpg.program), which overrides all file-level config including the bind-mounted .git/config. Extend that same injection — at least for bind workspace mode — to add:

  • core.checkStat=minimal
  • core.trustctime=false

This is env-based (no file mutation), overrides every config level, and is harmless in snapshot mode too. Requires generalizing the currently-hardcoded GIT_CONFIG_COUNT=1 into a counter so it composes with the existing gpg.program entry.

Scope / classification

Underlying cause is a git + Docker-bind-on-macOS interaction, not clawker code doing something wrong — but clawker chooses bind mode + UID remap and owns the container git config, so the mitigation belongs here. Affects any user doing rebase/checkout/merge inside a bind-mode container; reported as recurring.

Workaround (today)

Inside the container: git config core.checkStat minimal && git config core.trustctime false (repo-local or global), or perform the rebase on the host.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions