`Commit._deserialize` compared a 10-byte slice of each stripped header
line against the 9-byte literal `b"encoding "`, so the comparison never
matched and the branch reading a commit's declared encoding was
unreachable. Every commit parsed from the object database was decoded
with the default UTF-8: `Commit.encoding` reported `UTF-8` regardless of
the header, and the author, committer, and message of a commit written
under `i18n.commitencoding` came back with U+FFFD replacement characters
while `git log` shows them correctly. Re-serializing such a commit also
dropped its `encoding` header and stored the garbled text.
Compare the right slice length so the header is read. Adopt the declared
encoding only when Python has a text codec for it: the identity lines
are decoded with `errors="replace"`, which does not guard against an
unknown codec name, so a commit declaring one would otherwise raise
`LookupError` on attribute access. An unknown name keeps the previous
behavior (the default encoding) and logs the error.
Validated against a repository committed under `i18n.commitencoding =
ISO-8859-1`: `commit.encoding`, `commit.author.name`, and
`commit.message` now match what `git log` shows. Adds regression tests
in `test/test_commit.py` that fail before the change.
Commit._deserialize tests each header line with buf[0:10] == b"encoding ". The slice is 10 bytes, the literal is 9, and buf is stripped, so the comparison never matches and the branch that reads a commit's declared encoding is unreachable: every commit read from the object database is decoded with the default UTF-8. For a repository committed under i18n.commitencoding = ISO-8859-1:
so the identity and message GitPython reports for a commit differ from what git shows for the same object, and re-serializing such a commit drops its encoding header and stores the garbled text. Commit headers come from whoever authored the commit, including commits fetched from untrusted repositories.
Fixing the slice alone would introduce a crash: the identity lines decode with errors="replace", which does not guard against an unknown codec name, so a commit declaring encoding pony-speak would raise LookupError from any attribute access. The declared encoding is adopted only when Python has a text codec for it, probed with a one-byte decode because decoding b"" skips the codec lookup; an unknown name keeps the previous default-encoding behavior and logs the error. Adds regression tests for both cases in test/test_commit.py; the first fails before the change.