git: pin the git output contract and declare a minimum git version #524
Labels
No labels
breaking
bug
documentation
enhancement
epic
good first issue
help wanted
refactoring
resolution/duplicate
resolution/invalid
resolution/wontfix
security
severity/critical
severity/high
severity/low
severity/medium
status/abandoned
status/blocked
status/needs-decision
status/needs-info
status/needs-verification
testing
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
#525 ci(drift): run the git-touching tests against a git version matrix on the cron
sixfold-space/madtea
#526 Epic: madtea has no way to stay current with the git binary
sixfold-space/madtea
#527 git: replace the 17 Run* variants with one call that takes options
sixfold-space/madtea
Reference
sixfold-space/madtea#524
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 1 of the git-currency work. See the epic for the full picture.
What happens
madtea shells out to the
gitbinary. There is nogo-gitand no libgit2 ingo.mod, andinternal/service/git/holds about 25 source files that run git and parse what it prints. So git is an undeclared runtime dependency with an unpinned output contract.Two concrete gaps:
--porcelaincall site uses the bare, unversioned form. There are 35 of them acrossinternal/. None use--porcelain=v1. Git documents the unversioned default as free to change, and tells scripts to name the version they parse.git --versionfor a gate. The only--versioncalls are madtea's own binary and the installed-binary check atinternal/cmd/install/install.go:976.The failure mode is quiet. A user on a newer git gets a
--porcelainparse that returns the wrong thing instatus,stage, orworktree, and nothing reports an error.Fix
--porcelainsite to--porcelain=v1, so the parsed format is named, not inherited.--formatwhere a porcelain parse is doing plumbing work. The explicit--format=sites are already the stable ones.Acceptance
--porcelainremains ininternal/, and a test enforces that.Decided: the minimum git version is 2.38.0. There is one floor for every command, and no per-feature checks.
Why 2.38
madtea uses two git features newer than 2.29:
git merge-tree --write-treeininternal/cmd/pr/conflicts.go:74needs 2.38 (RelNotes 2.38.0).git rev-parse --end-of-optionsininternal/service/git/refinspect.go:587needs 2.30 (RelNotes 2.30.0).All other flags found are older:
--end-of-optionson other commands (2.24),branch --show-current(2.22),sparse-checkout list(2.25).LTS git versions
Also in scope for this issue
CONFLICTin merge, rebase, cherry-pick, revert, and stash, plusalready existsandnon-fast-forward). Git translates these messages (the German catalog hasKONFLIKT (%s): Merge-Konflikt in %s). SetLC_ALL=Con every git call, as lazygit (LANG=C LC_ALL=C LC_MESSAGES=C) and git-lfs (LC_ALL=C.UTF-8) do.git status --porcelain=v1andgit worktree list --porcelainare the documented stable forms, and the docs recommend-z.Not yet checked
git $cmd --end-of-options --rev -- --pathfor some commands. madtea uses that form withlogandgrep. The #525 matrix run on 2.38 will show whether it works there.madtea git ..., the-cconfig keys, and format placeholders were not checked against git versions.Closed by PR 529, merged to main as
975e6d15.What landed:
internal/gitexecbuilds every git child process and putsLC_ALL=Clast in the environment. Every directexec.Command("git", ...)call now uses it.gitexec.EnsureMinVersionchecks git 2.38.0 once per process, on the plain runners, the unauthenticated clone, and both transports. Below the floor the error names the found version and the required version.git statususes--porcelain=v1.git worktree listkeeps the bare flag, because git offers no versioned form there and documents that format as stable. The record states this exception.--porcelain. A UTF-8 test proves a commit subject and a file path read back unchanged underLC_ALL=C.The decision is recorded in
docs/decisions/0038-git-cli-minimum-version-and-output-contract.md(accepted).Gate: PASS, all 18 checks, on the merged tree.
Open follow-ups: the git version matrix in CI (issue 525), and the 17
Run*variants (issue 527).