git matches section names and variable names case-insensitively; only the subsection between quotes is case-sensitive. GitConfigParser matches all three exactly, so a config written with different casing is unreadable through it.
Against this file:
[core]
BigName = 1
[REMOTE "Origin"]
url = u
lookup git GitPython
core.BigName 1 1
core.bigname 1 NoOptionError
REMOTE "Origin".url u u
remote "Origin".url u NoSectionError
The variable half comes from optionxform being overridden to identity (git/config.py:439):
def optionxform(self, optionstr: str) -> str:
"""Do not transform options in any way when writing."""
return optionstr
The docstring says "when writing", and preserving case on write is right, since git keeps the spelling it was given. The same function decides how lookups are matched though, so reads inherit it.
This bites when the file was written by something other than GitPython: git itself preserves whatever casing the user typed, and other tools emit [remote "x"] or [Remote "x"] interchangeably, so repo.config_reader().get_value("remote \"x\"", "url") can raise on a perfectly valid config.
I have not sent a patch because the fix is a behaviour change with more than one shape: case-folding lookups only, or folding on read while keeping the written spelling, and either way sections() and items() start returning something different from what they return today. Happy to do it if you say which.
Unrelated to #2237, which I filed yesterday about valueless keys, but both are in the same _read/lookup path so you may want to look at them together.
git 2.50.1, GitPython at a9913c7.
Assisted-by: Claude Opus 5 (Claude Code), per the identification rule in CONTRIBUTING.md.
git matches section names and variable names case-insensitively; only the subsection between quotes is case-sensitive.
GitConfigParsermatches all three exactly, so a config written with different casing is unreadable through it.Against this file:
The variable half comes from
optionxformbeing overridden to identity (git/config.py:439):The docstring says "when writing", and preserving case on write is right, since git keeps the spelling it was given. The same function decides how lookups are matched though, so reads inherit it.
This bites when the file was written by something other than GitPython: git itself preserves whatever casing the user typed, and other tools emit
[remote "x"]or[Remote "x"]interchangeably, sorepo.config_reader().get_value("remote \"x\"", "url")can raise on a perfectly valid config.I have not sent a patch because the fix is a behaviour change with more than one shape: case-folding lookups only, or folding on read while keeping the written spelling, and either way
sections()anditems()start returning something different from what they return today. Happy to do it if you say which.Unrelated to #2237, which I filed yesterday about valueless keys, but both are in the same
_read/lookup path so you may want to look at them together.git 2.50.1, GitPython at a9913c7.
Assisted-by: Claude Opus 5 (Claude Code), per the identification rule in CONTRIBUTING.md.