Watch at EaseStories. Answers. Perspective.

Technology · PRACTICAL GUIDE

Git says index.lock exists? Prove the owner before deleting anything

The lock may belong to a live Git writer, a crashed process, a hook or IDE that recreates it, or an unwritable repository. Resolve the real lock path, identify any holder, preserve staged state and repair only the proven boundary.

Original diagram showing the locate, observe, classify and repair sequence for Git index.lock.
Original illustration: resolve the effective path and prove the holder before deleting a lock. Watch at Ease

index.lock is Git’s guard for an index update, not trash to delete on sight. The same message can mean a live writer, a crash residue, a hook or IDE that keeps recreating the file, or a repository that cannot complete an atomic rename.

Use an evidence ledger: resolve the effective lock path, preserve staged state, identify any holder, classify recurrence or writability, then make one narrow repair and verify the index afterward.

Preserve state and resolve the real lock path

Save the complete error, then run git status and git diff --cached --stat so you know whether the index already contains intended staged changes. Do not delete .git/index: that is the real binary index, not the temporary lock. In a linked worktree or with GIT_INDEX_FILE, the path may not be .git/index.lock. Use git rev-parse --path-format=absolute --git-path index.lock to resolve the path Git will actually use.

Record whether the resolved file exists, its owner, permissions, size and modification time. A zero-byte or old file is suggestive but not proof that it is stale. Git creates index.lock to exclude another writer while building a new index, then atomically renames or rolls it back. Removing that file while a writer is alive can defeat the protection the lock provides.

Prove whether a process owns or recreates it

On Linux or macOS, query the exact path with lsof; on Windows, search that path in Process Explorer or Sysinternals Handle. Identify the process, account and parent before stopping anything. The holder may be a Git command waiting for an editor, an IDE, a GUI client, a hook, a background indexer or an automation agent. Let a legitimate operation finish or close it through its own interface when possible.

If no process currently owns the file, watch what happens after a controlled retry. A lock that immediately returns points to a recurring producer or two overlapping Git commands, not stale debris. Pause the IDE, hook, watcher or job and serialize its Git writes. Repeatedly deleting the file only shortens the race and can make the failure intermittent.

Remove only a confirmed stale lock

A stale case requires all of these facts: the exact resolved path exists, no holder is found, the originating Git operation is no longer running, and the file does not immediately reappear. Preserve status and the staged summary first, then remove only that index.lock path. Do not remove index, HEAD, refs or unrelated .lock files as a bundle.

Run one harmless read such as git status, then retry the original single write. Confirm that index.lock disappears after success and that git diff --cached still contains only the changes you intended. If Git reports a different lock path, return to path resolution; do not broaden the deletion command.

Treat permission and unlink errors as a different failure

If Git cannot create, rename or unlink the lock, inspect ownership and writability of the resolved Git directory and its filesystem. A repository on a Windows-mounted WSL path, a network share, container bind mount or security-scanned directory can behave differently from a local filesystem. Test with the same user and environment that runs Git.

Do not use sudo git or recursively chown a broad tree as a generic cure. Those actions can create mixed ownership or alter unrelated files. Repair the narrow owner, mount, antivirus or policy boundary that the evidence identifies, then retest without privilege escalation.

Close the incident with a reproducible check

Run the original Git write once, not from two terminals. Verify the exit code, confirm the lock is gone, inspect git status and git diff --cached, and record which process or stale file caused the block. If a hook modifies the index, review that design instead of hiding the conflict with --no-verify.

For automation, serialize commands that write the same index and log their start, end and repository path. Separate worktrees have separate index state, but the resolved path is still the authority. A future lock incident should be diagnosable from the ledger without guessing or deleting repository metadata.

Original decision tree for a live or recurring Git writer versus an ownerless stale lock.
Original illustration: live, stale and unwritable lock cases require different repairs. Watch at Ease