Subject: Re: bug: git config --global --unset doesn't unset configs in corner case

From: Patrick Steinhardt <[email-masked]>
Date: Fri, 10 May 2024 11:56:58 +0200

On Thu, May 09, 2024 at 09:23:13AM -0700, Junio C Hamano wrote:
> Mike Hommey <[email-masked]> writes:
> 
> > When both ~/.gitconfig and ~/.config/git/config exist, git will read
> > both. But when using `git config --global --unset`, it will only touch
> > the first one. So unsetting config items from ~/.config/git/config is
> > not possible from the command line when ~/.gitconfig exists.

This actually works as documented:

  --global

    For writing options: write to global ~/.gitconfig file rather than
    the repository .git/config, write to $XDG_CONFIG_HOME/git/config
    file if this file exists and the ~/.gitconfig file doesn’t.

    For reading options: read only from global ~/.gitconfig and from
    $XDG_CONFIG_HOME/git/config rather than from all available files.

    See also the section called “FILES”.

Whether that behaviour is sane is a different question though.

> Interesting observation of an understandable behaviour.
> 
> I think the original intent of limiting the writing to just one was
> to avoid having both files in the first place.  When both do exist
> already, I am not sure what the right behaviour on the write side
> should be.  We could special case "--unset-all" and remove from
> both, but "--unset" is to remove just one, so when the reading side
> reads from both, it becomes "which one to remove"?
> 
> Comments from those who are more familiar with the "git config" are
> certainly appreciated.

Honestly, I even think that the reading behaviour is weird. For almost
all the other tools that I know of that did the XDG migration, they only
ever read either the XDG config or the one located in the users' home
directory. I think this behaviour is quite sensible and leads to less
surprises overall, also to avoid asymmetric behaviour like the reported
one.

In any case, I find the expectation that `--unset-all` unsets all config
reasonable. But what about `--remove-section` and `--rename-section`? If
a section exists in both files, should it be renamed in both? And
removed in both? What if you set a value with a value pattern (`git
config foo.bar baz pattern`)? I think the answers are less clear in
those cases, and that to me hints that the design of how this feature
works is off.

As said, the most reasonable behaviour would be if we started to only
ever use _either_ the XDG _or_ the home config, but never both. This not
only solves the reported issue, where it's unclear which of the files
should be modified. It also solves other problems -- would you for
example know the precedence order of those two files?

I have no idea though whether this is something that we can reasonably
change now. I doubt that many users rely on having both configs, and
I cannot think of any reason why they knowingly would. But it would be a
potentially breaking change regardless of that.

Patrick