libgit2 ignores GIT_CONFIG_GLOBAL and still reads ~/.gitconfig and ~/.config/git/config
Symptom#
Tests isolate git's config with GIT_CONFIG_GLOBAL=/dev/null. The git side of a git-vs-tool comparison then ignores the user's global config, but the tool built on libgit2 (git2 crate) still sees it, so results differ only on machines with a global config. Seen in rgit: two rebase tests failed because the developer's ~/.config/git/config sets rebase.updateRefs=true; another run picked up commit.gpgSign.
Cause#
git reads GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM and GIT_CONFIG_NOSYSTEM and then does not read ~/.gitconfig, the XDG file or the system file. libgit2's Repository::config() and Config::open_default() do not look at these variables; they use their own search paths for the global, XDG and system levels.
Fix#
- In the tool: when opening a repository, set libgit2's search paths from the variables, the way git resolves them, with
git2::opts::set_search_path(ConfigLevel::Global | Xdg | System, ...)(once per process). Point the global level atGIT_CONFIG_GLOBAL's folder or an empty path, clear XDG whenGIT_CONFIG_GLOBALis set, and clear System underGIT_CONFIG_NOSYSTEM. Route config reads outside a repository through the same stacking. - In tests of a libgit2 tool: also set
HOMEandXDG_CONFIG_HOMEto an empty temp folder, not onlyGIT_CONFIG_GLOBAL.
See also A test that shells out to a real CLI with side effects can change the user's real config.
Evidence#
rgit, 2026-09-27/28: with only GIT_CONFIG_GLOBAL=/dev/null, git ignored ~/.config/git/config (which set rebase.updateRefs=true) and libgit2 read it, so two twin-repo rebase tests in crates/rgit-cli/tests/sequencer.rs failed; setting HOME and XDG_CONFIG_HOME in the test helpers fixed them. The tool-side fix is in rgit's global-options work, with a test in crates/rgit-cli/tests/globals.rs that puts a ~/.gitconfig, an XDG file and a GIT_CONFIG_GLOBAL file in a temp HOME and checks that only the GIT_CONFIG_GLOBAL file is read (commit author identity).