Source control lists the git directory's own files as changes when the git dir is outside the work tree
Lapce Version
0.4.6, built from master (c9e4c339)
System information
Windows 10 Enterprise LTSC 1809 (where it was observed in the panel); also confirmed against libgit2 on Windows 11 Pro (10.0.26200)
Describe the bug
When a repository keeps its git directory outside the work tree — the layout
git init --separate-git-dir produces, where .git is a file containing
gitdir: <path> — the source control panel lists the contents of that git
directory as unversioned changes: config, HEAD, index,
COMMIT_EDITMSG, object files, and any unrelated files that happen to sit
next to it.
git status on the same repository is clean and reports only the real
modifications. Only Lapce shows the extra entries.
Reproduction
mkdir -p parent/work parent/gitdirs
cd parent/work
git init --separate-git-dir ../gitdirs/test.git
echo hello > file.txt && git add . && git commit -m initOpen parent/work in Lapce. The source control panel lists
test.git/config, test.git/HEAD and so on, none of which are part of the
repository.
Additional information
The cause is a difference between git and libgit2 in how the work tree is derived:
- git derives the work tree from the location of the
.gitfile - libgit2 reads
core.worktreefrom the config and, when that is absent, falls back to the parent directory of the git directory
git init --separate-git-dir does not write core.worktree, so this is a
state git itself creates and treats as complete. The fallback directory
usually holds unrelated files — including the git directory itself — and that
is what ends up in the panel.
Lapce reaches libgit2 through Repository::discover in
lapce-proxy/src/dispatch.rs, without setting a work tree of its own.
The numbers below come from a small test program using the same binding Lapce depends on (git2 0.20.2, libgit2 1.9.0), run against the layout from the reproduction steps above:
Repository::discover("parent/work")
workdir : parent/gitdirs/ <- parent of the git dir, not the work tree
statuses: 28 <- test.git/config, test.git/HEAD, objects, ...For comparison, git -C parent/work rev-parse --show-toplevel reports
parent/work and git status is clean — the repository has no modifications
at this point at all, so every one of those 28 entries is spurious.
Setting core.worktree manually works around it, but that means writing to
the config of a repository the editor only reads from — and repositories
created with --separate-git-dir will keep showing up without it.
I have a fix ready and would be happy to open a PR: correcting the work tree
on the repository handle after Repository::discover (nothing written to the
config) resolves it, and leaves repositories whose work tree is already
correct untouched.
This text has been written with the help of AI.
Source: lapce/lapce