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

From: Tim Landscheidt <[email-masked]>
Date: Sun, 24 Mar 2024 18:57:21 +0000

Junio C Hamano <[email-masked]> wrote:

> […]

>> 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.

I respectfully disagree (somewhat).  git-config(1) reads:

| […]

|        Multiple lines can be added to an option by using
|        the --add option. If you want to update or unset an
|        option which can occur on multiple lines, a
|        value-pattern (which is an extended regular
|        expression, unless the --fixed-value option is
|        given) needs to be given. Only the existing values
|        that match the pattern are updated or unset. If you
|        want to handle the lines that do not match the
|        pattern, just prepend a single exclamation mark in
|        front (see also the section called “EXAMPLES”), but
|        note that this only works when the --fixed-value
|        option is not in use.

| […]

|        --replace-all
|            Default behavior is to replace at most one
|            line. This replaces all lines matching the key
|            (and optionally the value-pattern).

This says quite clearly if one wants to /add/ a value,
"--add" must be given; the default is to /replace/ an
existing value.

The only indication that this might be false is the
description of "--add" itself which gives another and
different explanation for the behaviour of "--replace-all":

|        --add
|            Adds a new line to the option without altering
|            any existing values. This is the same as
|            providing ^$ as the value-pattern in
|            --replace-all.

| […]

So the first section states that "only the existing values
that match the pattern are updated or unset", and here it
says that if there are no matches, a new line is added.

>> 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.

> […]

The standard way to achieve this would be to use "--",
i. e. "git config section.key --add -- --add" (apparently
even part of POSIX as "Utility Syntax Guidelines", but also
commonly used elsewhere in Git).

Tim