Subject: Re: [PATCH 3/6] Teach "git remote" about remote.default.

From: Marc Branchaud <[email-masked]>
Date: Fri, 13 Jul 2012 15:54:00 -0400

On 12-07-11 05:55 PM, Junio C Hamano wrote:
> Marc Branchaud <[email-masked]> writes:
> 
>> What about a warning displayed if "remote.default" is not set?  Something like:
>>
>> 	This repository does not have an explicitly configured default
>> 	remote.  Selecting "origin" as the default remote repository.
>> 	To suppress this warning, or if you wish to have a different
>> 	default remote repository, run "git remote default <name>".
>> 	In git X.Y, the default remote will be automatically configured
>> 	as the first remote added to the repository.
> 
> When do you plan to issue the above message?  Any time we default to
> 'origin' without remote.default?  
> 
> I do not see a value to it---if the user has been happily using
> 'origin' as the default remote, there is no reason to give such a
> noise.  We will keep defaulting to 'origin' even in the version of
> Git with this series in it.
> 
> A warning is necessary if we plan to _later_ add the "first remote
> created either by 'git clone' or 'git remote add' is automatically
> set as the value for remote.default configuration" feature, and the
> place to do so is "git clone" and "git remote add" that creates the
> first remote for the repository.  If the name of the remote created
> by them is 'origin', then there is no need for warning, but if the
> user called that first remote with a name that is _not_ 'origin',
> later versions of Git will change the behaviour.
> 
> I can see a transition plan that goes like this:

I like your plan -- thanks for working it out in such detail!

I'll re-roll the series to work like your plan's Step 0, and I'll post a
separate RFC patch on top of it that initiates the transition, so folks can
discuss it specifically.

> Step 0.  With this series but without the "first one becomes default"
> 
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     hint: You may want to run "git remote default upstream" now so that
>     hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
>     hint: repository, instead of 'origin' (which you do not yet have).
> 
>     $ git config --global advice.settingDefaultRemote false
>     $ git remote rm upstream
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing, as the user declined the advice ...
> 
> Step 1.  "First one becomes default" as an opt-in feature
> 
>     $ git config --global --unset advice.settingDefaultRemote
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     hint: You may want to run "git remote default upstream" now so that
>     hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
>     hint: repository, instead of 'origin' (which you do not yet have).
>     hint: "git config --global remote.firstRemoteBecomesDefault true" can be
>     hint: used to make the first remote added to the repository the default
>     hint: remote automatically.
>     $ git remote default
>     origin
> 
>     $ git config --global remote.firstRemoteBecomesDefault true
>     $ git remote rm upstream
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing; user already knows about remote.firstRemoteBecomesDefault
>     $ git remote default
>     upstream
> 
> Step 2.  Start warning the default change for "First one becomes default"
> 
>     $ git config --global --unset advice.settingDefaultRemote
>     $ git config --global --unset remote.firstRemoteBecomesDefault
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     hint: You may want to run "git remote default upstream" now so that
>     hint: a lazy 'git push' and 'git fetch' defaults to this 'upstream'
>     hint: repository, instead of 'origin' (which you do not yet have).
>     hint: "git config --global remote.firstRemoteBecomesDefault true" can be
>     hint: used to make the first remote added to the repository the default
>     hint: remote automatically.
>     hint:
>     hint: In future versions of Git, this will happen automatically.
>     hint: If you do not want the first remote to become default, run
>     hint: "git config --global remote.firstRemoteBecomesDefault false" now.
> 
> Step 3. "First one becomes default" is now default
> 
>     $ git config --global --unset advice.settingDefaultRemote
>     $ git config --global --unset remote.firstRemoteBecomesDefault
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     warning: Made 'upstream' the default remote for this repository.
>     $ git remote default
>     upstream
> 
>     $ git remote rm upstream
>     $ git config --global remote.firstRemoteBecomesDefault true
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing; the user explicitly told us what to do
>     $ git remote default
>     upstream
> 
>     $ git remote rm upstream
>     $ git config --global remote.firstRemoteBecomesDefault false
>     $ git init
>     $ git remote add upstream git://over.there.xz/git.git/
>     ... nothing; the user explicitly told us what to do
>     $ git remote default
>     origin
> 
>> Since the "cmd_" prefix is already used for the main commands, perhaps
>> another prefix for subcommands?  Maybe "sub_"?  Some of the shell-based
>> commands use the main command itself as a prefix (e.g. bisect_start()).
>> Doing that here would mean "remote_default()" etc.  Any preference?
> 
> No strong preference for file-scope-statics.
> 
>>>> +{
>>>> +	if (argc < 2)
>>>> +		printf_ln("%s", remote_get_default_name());
>>>
>>> Good.  If somebody anal cares about the vanilla hardcoded default
>>> 'origin' and 'remote.default' having 'origin' as a configured value,
>>> he should be using "git config" to ask the difference.  Users of
>>> "remote default" interface should not have to care.
>>>
>>>> +	else {
>>>> +		const char *name = argv[1];
>>>> +		if (remote_is_configured(name)) {
>>>> +			git_config_set("remote.default", name);
>>>> +			printf_ln(_("Default remote set to '%s'."), name);
>>>> +		} else
>>>> +			return error(_("No remote named '%s'."), name);
>>>> +	}
>>>
>>> I am not sure if this is a good idea.  Shouldn't "git remote default
>>> frotz" followed by "git remote add frotz" work?
>>
>> To me it feels wrong to allow the user to set the default remote to something
>> that doesn't actually exist.  It's like trying to add a non-existent file.
> 
> Every few weeks, I do this:
> 
> 	ln -f -s Documentation/RelNotes/$new_version.txt RelNotes
>         edit Documentation/RelNotes/$new_version.txt
> 
>> And what if the user forgets the second step?
> 
> That is why we warn on an unusual order.  A lazy "git push" will
> fail and that would be sufficient clue.
> 
> And another reason for the warning (with "you do not yet have") is
> to prevent this:
> 
>         git remote add frotz git://over.there.xz/git.git
>         git remote default frozt

See, to me an error in this case makes more sense.  But I feel I'm splitting
hairs now, and I'm happy to go with the warning instead.

>> It seems saner for a command to fail if it knows a change it's about to make
>> will cause problems.
> 
> The point is that you do *NOT* know it will cause problems.  People
> who want to do things in an unusual order *know* what they are doing
> a lot better than you do.  Don't get in their way.

I'll aim to post a revised series next week.

		M.