Subject: Re: [PATCH v4 9/9] checkout & worktree: introduce checkout.defaultRemote

From: Ævar Arnfjörð Bjarmason <[email-masked]>
Date: Fri, 01 Jun 2018 11:47:32 +0200

On Thu, May 31 2018, Stefan Beller wrote:

> Hi Ævar,
>
> Sorry for chiming in late. I have a couple of thoughts:
>
>>     (
>>         cd /tmp &&
>>         rm -rf tbdiff &&
>>         git clone [email-masked]:trast/tbdiff.git &&
>>         cd tbdiff &&
>>         git branch -m topic &&
>>         git checkout master
>>     )
>>
>> That will output:
>>
>>     Branch 'master' set up to track remote branch 'master' from 'origin'.
>>     Switched to a new branch 'master'
>
> I thought master is already there after the clone operation and
> you'd merely switch back to the local branch that was created at
> clone time?
>
>     $ git clone [email-masked]:trast/tbdiff.git && cd tbdiff
>     $ git branch
>     * master
>     $ cat .git/config
> ...
> [branch "master"]
>     remote = origin
>     merge = refs/heads/master
>
> But the observation is right, we get that message. When do we
> do the setup for the master branch specifically?

What you're missing is this part:

    git branch -m topic

I.e. we clone the repo, and have a "master" branch, we then rename
"master" to "topic", now there's no local master branch. Then we
checkout master either with only one remote or two.

>>
>> But as soon as a new remote is added (e.g. just to inspect something
>> from someone else) the DWIMery goes away:
>>
>>     (
>>         cd /tmp &&
>>         rm -rf tbdiff &&
>>         git clone [email-masked]:trast/tbdiff.git &&
>>         cd tbdiff &&
>>         git branch -m topic &&
>>         git remote add avar [email-masked]:avar/tbdiff.git &&
>>         git fetch avar &&
>>         git checkout master
>>     )
>>
>> Will output (without the advice output added earlier in this series):
>>
>>     error: pathspec 'master' did not match any file(s) known to git.
>>
>> The new checkout.defaultRemote config allows me to say that whenever
>> that ambiguity comes up I'd like to prefer "origin", and it'll still
>> work as though the only remote I had was "origin".
>>
>> Also adjust the advice.checkoutAmbiguousRemoteBranchName message to
>> mention this new config setting to the user, the full output on my
>> git.git is now (the last paragraph is new):
>>
>>     $ ./git --exec-path=$PWD checkout master
>>     error: pathspec 'master' did not match any file(s) known to git.
>>     hint: The argument 'master' matched more than one remote tracking branch.
>>     hint: We found 26 remotes with a reference that matched. So we fell back
>>     hint: on trying to resolve the argument as a path, but failed there too!
>>     hint:
>>     hint: Perhaps you meant fully qualify the branch name? E.g. origin/<name>
>
> s/meant fully/meant to fully/
> s/? E.g./?\nFor example/

Thanks, will fix.

>>     hint: instead of <name>?
>
> In builtin/submodule--helper.c there is get_default_remote() which also
> hardcodes "origin". I think that is a safe thing to do.
>
>>     hint:
>>     hint: If you'd like to always have checkouts of 'master' prefer one remote,
>>     hint: e.g. the 'origin' remote, consider setting checkout.defaultRemote=origin
>>     hint: in your config. See the 'git-config' manual page for details.
>
> his new setting elevates one remote over all others, which may
> be enough for most setups and not confusing, too.
> Consider the following:
>
>     git clone https://kernel.googlesource.com/pub/scm/git/git && cd git
>     git remote add gitster https://github.com/gitster/git
>     git remote add interesting-patches https://github.com/avar/git
>     git remote add my-github https://github.com/stefanbeller/git
>
>     git checkout master
>
> This probably means I want to have origin/master (from kernel.org)
>
>     git checkout ab/checkout-implicit-remote
>
> This probably wants to have it from gitster/ (as it is not found on kernel.org);
> I am not sure if it would want to look at interesting-patches/ that mirrors
> github, but probably if it were not to be found at gitster.
>
> So maybe we rather want a setup to give a defined priority for
> the search order:
>
>   git config dwim.remoteSearchOrder origin gitster avar
>
> Stepping back a bit, there is already an order in the config file
> for the remotes, and that order is used for example for 'fetch --all'.
>
> I wonder if we want to take that order? (Or are the days of hand
> editing the config over and this is too arcane? We would need a
> config command to re order remotes). Then we could just have a
> boolean switch to use the config order on ambiguity.
> Although you might want to have a different order for fetching
> and looking for the right checkout.

I thought about this use-case, and if we want this in the future I think
the most straightforward way is not to invent some new search order
variable, but just make use of git config allowing multi-values, i.e.:

    [checkout]
        defaultRemote = origin
        defaultRemote = gitster

Although I'm not interested in implementing that now, and unlike just
having one special remote I don't think it's of interest to the vast
majority of git users.

>> I considered splitting this into checkout.defaultRemote and
>> worktree.defaultRemote, but it's probably less confusing to break our
>> own rules that anything shared between config should live in core.*
>> than have two config settings, and I couldn't come up with a short
>> name under core.* that made sense (core.defaultRemoteForCheckout?).
>
>   core.dwimRemote ? It's a bit cryptic, though.

Covered by Eric's reply in
<[email-masked]>

>> See also 70c9ac2f19 ("DWIM "git checkout frotz" to "git checkout -b
>> frotz origin/frotz"", 2009-10-18) which introduced this DWIM feature
>> to begin with, and 4e85333197 ("worktree: make add <path> <branch>
>> dwim", 2017-11-26) which added it to git-worktree.