Subject: Re: "git worktree repair" modifies the wrong repository

From: Junio C Hamano <[email-masked]>
Date: Fri, 04 Oct 2024 08:50:26 -0700

[email-masked] writes:

> "git clone --mirror" sets up a fetch refspec that forcibly update
> "refs/heads/*" when fetching. This means fetching overwrites your
> local branches and I think the fetch fails if you have a branch
> checked out that it wants to update. "git clone --bare" does not set
> up any fetch refspec. In both cases there are no remote tracking
> branches to base your local work on.
>
>> Regarding core.bare: That's one of the settings which is special-cased
>> (hard-coded) to work "properly" when extensions.worktreeConfig is not
>> enabled, so it's not clear what problem you were experiencing in that
>> regard. In my testing, `git rev-parse --is-bare-repository` correctly
>> reported "true" in the bare repository, and "false" in a worktree
>> hanging off the bare repository even when extensions.worktreeConfig
>> was not enabled.
>
> I've a feeling I thought I needed to set it because I didn't realize
> that core.bare was special cased rather than doing so in response to a
> particular problem but I can't remember for sure.

I recently encountered a funny behaviour in a worktree linked to a
bare repository.

    $ git clone --bare file://$(pwd)/git.git victim-00.git
    $ git -C victim-00.git worktree add ../victim-01
    $ cd victim-01
    $ git grep -i -e subscribe
    fatal: this operation must be run in a work tree

Of course, "git grep -i subscribe HEAD" works (as it does not
require a working tree and works on a proper bare repository).

What is curious is that this also works:

    $ git grep -i -e subscribe --cached

That mode of operation can work only when the index exists,
which means it needs a working tree.  Perhaps the working tree
version is written in a more strict way to avoid unexpected
behaviour (and gets the implementation of strictness wrong), while
the index version has no such protection?  Running the index version
in the bare repository

    $ git -C ../victim-00.git -i -e subscribe --cached; echo $?
    1

seems to confirm.  The command does not fail, but in a bare
repository, the in-core the_index has 0 elements, so it thinks it
successfully looked for the needle in the haystack and found
nothing, without complaining "hey, there is no haystack".

With the extensions.worktreeConfig things work as expected in the
worktree linked to the bare repository, like so:

    $ cd ../victim-01
    $ git config set extensions.worktreeConfig true
    $ git config set core.bare false
    $ git grep -i -e subscribe

So, I dunno.  Is core.bare really "special cased"?  It seems to me
that any halfway special case harms users more than helps.