Skip to content

Conversation

@sambostock
Copy link

@sambostock sambostock commented Oct 21, 2025

From git config's documentation:

The files are read in the order given above, with last value found taking precedence over values read earlier.

Currently, we discard values if we already have one with the same priority. However, this gives us "first one wins" semantics, which is incorrect.

By instead only discarding values if we already have one with a higher priority, we can achieve "last one wins" semantics, matching git.


This is of particular importance because we use config values to resolve the nickname and ruleset fields, so the value we resolve must match what a user would expect when writing their config. For example, consider the following git config:

[otel.trace2]
  ruleset = dl:drop # Drop traces by default)

[includeIf "hasconfig:remote.*.url:https://example.com/my-repo.git"]
  path = my-repo-tracing.gitconfig

and in my-repo-tracing.gitconfig

[otel.trace2]
  ruleset = dl:verbose # Collect detailed traces for my-repo

Because we have "first one wins" semantics instead of git's "last one wins" semantics, the override doesn't do anything and traces are dropped unconditionally.

From `git config`'s documentation:

> The files are read in the order given above, with last value found taking precedence over values read earlier.

Currently, we discard values if we already have one with the same
priority. However, this gives us "first one wins" semantics, which is
incorrect.

By instead only discarding values if we already have one with a higher
priority, we can achieve "last one wins" semantics, matching `git`.

This is of particular importance because we use config values to resolve
the nickname and ruleset fields, so the value we resolve must match what
a user would expect when writing their config. For example, consider the
following git config:

    [otel.trace2]
      ruleset = dl:drop # Drop traces by default)

    [includeIf "hasconfig:remote.*.url:https://example.com/my-repo.git"]
      path = my-repo-tracing.gitconfig

and in my-repo-tracing.gitconfig

    [otel.trace2]
      ruleset = dl:verbose # Collect detailed traces for my-repo

Because we have "first one wins" semantics instead of git's "last one
wins" semantics, the override doesn't do anything and traces are
dropped unconditionally.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant