Subject: Re: Inconsistent/buggy behaviour of "git config --add"

From: Junio C Hamano <[email-masked]>
Date: Sat, 23 Mar 2024 10:52:45 -0700

Tim Landscheidt <[email-masked]> writes:

> | # git config section.key value0
> | # git config --add section.key value1

The action verb --add comes immediately after "git config" (and
possibly file-option and type option), so this is a request to
append "key = value1" in the "[section]" (if there is no existing
section.key, then "[section]" would have to be created at the same
time, but in this case there already is one).

> | # cat .git/config
> | [core]
> |         repositoryformatversion = 0
> |         filemode = true
> |         bare = false
> |         logallrefupdates = true
> | [section]
> |         key = value0
> |         key = value1

So this makes perfect sense.

> | # git config section.key --add value2

No action verb immediately after "git config" (possibly after
file-option and type option).  This should be taken as

    git config <name> <value> <value-pattern>

where

    <name> = section.key
    <value> = --add
    <value-pattern> = value2

As we lack --replace-all, the default behaviour is to replace a
single existing entry of "section.key" with existing value "value2",
with the new value "--add", or if there is no such existing entry,
add one such entry.

> | # cat .git/config
> | [core]
> |         repositoryformatversion = 0
> |         filemode = true
> |         bare = false
> |         logallrefupdates = true
> | [section]
> |         key = value0
> |         key = value1
> |         key = --add

which seems to be what the code did.

> | # git config section.key --add

No action verb immediately after "git config" (possibly after
file-option and type option).  This should be taken as

    git config <name> <value>

where

    <name> = section.key
    <value> = --add

and is an attempt to replace existing section.key with the new value
"--add", but because we have already three such entries, we get 

> | warning: section.key has multiple values
> | error: cannot overwrite multiple values with a single value
> |        Use a regexp, --add or --replace-all to change section.key.
> | #

which sounds sensible.

> So on one hand, "--add" must be given before the key to add
> a line, but if on the other hand one passes the option after
> the key and before the value, it is literally taken as the
> value and the value does not seem to be interpreted as a
> value-pattern, either.  However, if the value is missing,
> Git correctly recognizes that this does not make sense.

Not really.  I agree that the "git config" syntax is messy, but I
followed your example with "git config --help" (especially its
SYNOPSIS section) in hand, and reached the above explanation, which
your conjecutre does not quite match.

> My expectation of least surprise is that "git config
> section.key --add value" should be equivalent to "git config
> --add section.key value".

You cannot have "--add" as a value by doing so.

> If that is not possible, I would expect "git config
> section.key --add value2" to mean "change the values of
> section.key to '--add' where they currently match the
> value-pattern of 'value2'".

I think your expectation needs to be updated in this particular
case, but there is a discussion to revamp the UI started elsewhere,
which stops the double-dashed action verbs and instead trigger
different actions as subcommands of "git config", which will
hopefully make things easier to understand.