Skip to content

feat(git-remote-entire): honour GIT_HTTP_USER_AGENT for the HTTP User-Agent - #2701

Merged
toothbrush merged 4 commits into
mainfrom
paul/http-user-agent-override
Oct 11, 2026
Merged

toothbrush merged 4 commits into
mainfrom
paul/http-user-agent-override

Conversation

@toothbrush

@toothbrush toothbrush commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

https://entire.io/gh/entireio/cli/trails/1519

Why

Anyone running git-remote-entire from automation (CI runners, Buildkite plugins, scripts) wants their traffic distinguishable in server access logs. Git already has the knob for this; the helper ignored it and always sent git-remote-entire/<version>.

What

git-remote-entire now honours git's own GIT_HTTP_USER_AGENT for the HTTP User-Agent header, matching git-config(1), http.userAgent:

The HTTP USER_AGENT string presented to an HTTP server. The default value represents the version of the Git client such as git/1.7.1. This option allows you to override this value to a more common value such as Mozilla/4.0. [...] Can be overridden by the GIT_HTTP_USER_AGENT environment variable.

Behaviour, verified against git 2.55.0 with a header-dumping server:

  • unset: helper default git-remote-entire/<version> (git: git/2.55.0)
  • set: value sent verbatim, any shape (git: same)
  • set but empty: no User-Agent header at all (git: same; curl drops the header for an empty CURLOPT_USERAGENT)

transport.Config.UserAgent == "" now sends no header instead of Go's Go-http-client/1.1, so the auth client and the git-transport client behave the same way.

A value net/http would refuse (CR, LF, NUL) fails up front with fatal: GIT_HTTP_USER_AGENT holds an invalid header character (exit 128) instead of every request dying on an anonymous header error.

The helper now strips ref-in-want from the v2 fetch= capability it relays to native git. It proxies each fetch POST to a replica, so a server-side want-ref lookup could race the ls-refs answer git already saw; the data plane hid the feature only for the default git-remote-entire/ User-Agent, which this override can change. A fetch line left with no feature becomes the bare key fetch, which gitprotocol-v2(5) allows (capability = PKT-LINE(key[=value] LF)).

Unchanged and deliberate:

  • The pkt-line agent= capability still carries the helper's own identifier. It is a single whitespace-free protocol token, so it is never user-controlled.
  • Nothing Entire-specific was added: no new env var, flag, or config key. Only git's own name.

Not done: the http.userAgent config key is not read. The helper never shells out to git config, and git forwards only -c overrides (not .gitconfig) to helpers via GIT_CONFIG_PARAMETERS, so supporting it would need a new subprocess for a partial result. Git documents the env var as the override that wins anyway.

Verification

  • go test ./cmd/git-remote-entire/... ./internal/remotehelper/... and go vet: pass
  • golangci-lint run on both packages: 0 issues; gofmt -l -s clean
  • New TestResolveHTTPUserAgent (table, parallel, env injected) and TestHTTPUserAgent_ReachesServer (builds the auth client as run() does against an httptest.Server and asserts the received header for default / override / empty)
  • TestProxy_EmptyUserAgentSendsNoHeader replaces the old "falls back to Go default" expectation
  • Git behaviour pinned empirically on git 2.55.0: GIT_HTTP_USER_AGENT="" sends no header; env beats -c http.userAgent; -c reaches a remote helper only as GIT_CONFIG_PARAMETERS='http.userAgent'='…'

🤖 Generated with Claude Code

…-Agent

Match git's own override for the HTTP User-Agent header: a set value
replaces the helper default verbatim and an empty value sends no header,
exactly as git 2.55 does. The pkt-line agent= capability keeps the
helper's own identifier; http.userAgent config is not read because the
helper never runs `git config`.

An empty transport.Config.UserAgent now sends no User-Agent header
instead of Go's default, so both HTTP surfaces agree.

Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
@toothbrush
toothbrush requested a review from a team as a code owner October 8, 2026 06:53
Copilot AI balanced review requested due to automatic review settings October 8, 2026 06:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation consistently covers both HTTP paths and includes focused regression tests.

0 open findings

What changed in this PR

Aligns git-remote-entire HTTP identification with Git’s GIT_HTTP_USER_AGENT behavior.

Changes:

  • Resolves HTTP user-agent overrides while preserving the fixed protocol agent.
  • Suppresses Go’s default header when the override is empty.
  • Adds documentation and coverage for default, overridden, and empty values.
File Description
README.md Documents the supported environment variable.
cmd/​git-remote-entire/​main.go Resolves and applies the HTTP user-agent.
cmd/​git-remote-entire/​main_test.go Tests resolution and auth-path requests.
internal/​remotehelper/​transport/​proxy.go Always wraps transports to support empty-header suppression.
internal/​remotehelper/​transport/​proxy_test.go Verifies empty values omit the header.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

toothbrush and others added 3 commits October 10, 2026 12:39
…re the auth client

Validate the override with httpguts.ValidHeaderFieldValue so a CR, LF or
NUL fails up front with a message naming GIT_HTTP_USER_AGENT, instead of
every request dying later on net/http's anonymous header error.

Extract newAuthHTTPClient from run() so the User-Agent test exercises
the chain the helper ships rather than a hand-built copy.

Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
…f User-Agent

The helper proxies each v2 fetch POST to a replica, so a server-side
want-ref lookup could race the ls-refs answer git already relayed. The
data plane hides ref-in-want only when the User-Agent starts with
git-remote-entire/, which GIT_HTTP_USER_AGENT can now change. Strip the
token from the relayed fetch= capability in the helper itself; the
server check stays as belt and braces.

A fetch line left with no feature becomes the bare key "fetch", which
gitprotocol-v2(5) allows (capability = PKT-LINE(key[=value] LF)).

Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
…sement

Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>
@toothbrush
toothbrush merged commit 57de2c3 into main Oct 11, 2026
18 checks passed
@toothbrush
toothbrush deleted the paul/http-user-agent-override branch October 11, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants