On Wed Nov 27, 2024 at 14:46, Junio C Hamano <gitster@xxxxxxxxx> wrote: > Bence Ferdinandy <bence@xxxxxxxxxxxxxx> writes: > >> Introduce a new setting, remote.$remote.followRemoteHEAD with four >> options: >> >> - "never": do not ever do anything, not even create >> - "create": the current behaviour, now the default behaviour >> - "warn": print a message if remote and local HEAD is different >> - "always": silently update HEAD on every change > > That seems to be plenty of choices to please many classes of users. > > Except for the one that I would want to use myself, which is "I > understand their HEAD points at branch X right now; please warn when > they flip their HEAD to a different branch, but until then please do > nothing". That's somewhere between "never" and "warn". Just to clarify, an example: the remote's HEAD is set to "master", and you have - git remote set-head origin next - git config set remote.origin.followRemoteHead "manual" - git config set remote.origin.followRemoteHeadManual "master" you manually set these explicitly. As long as the remote's HEAD is still "master" you do not get a warning when running fetch, but if it changes to something else (even "next"), you _do_ get a warning, that is not silenced until you set followRemoteHeadManual to "next". Would you expect `git remote set-head origin next` to set followRemoteHead to "manual" and to set the correct value for the followRemoteHeadManual to "master" if it actually changed the current refs/remote/origin/HEAD from master to next? Or is having this completely manual fine? I toyed with the thought of rolling the two settings together (an unrecognized string would mean the reference for which we must be silent), but then you couldn't have a remote/HEAD called "create" for example, so I think we need to store that separately. I'm also not quite happy with "followRemoteHeadManual" ... > >> @@ -1603,6 +1628,8 @@ static int set_head(const struct ref *remote_refs) >> string_list_append(&heads, strip_refshead(ref->name)); >> } >> >> + if (follow_remote_head < 0) >> + goto cleanup; > > There is some "magical" value(s) that is/are negative; we will find > out what they are later. > >> @@ -1614,6 +1641,7 @@ static int set_head(const struct ref *remote_refs) >> if (!head_name) >> goto cleanup; >> is_bare = is_bare_repository(); >> + create_only = follow_remote_head == 2 ? 0 : !is_bare; > > There is one more "magical" value that follow_remote_head can take. > >> @@ -1626,9 +1654,14 @@ static int set_head(const struct ref *remote_refs) >> result = 1; >> goto cleanup; >> } >> - if (refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf, >> - "fetch", NULL, !is_bare)) >> + was_detached = refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf, >> + "fetch", &b_local_head, create_only); >> + if (was_detached == -1) { >> result = 1; >> + goto cleanup; >> + } >> + if (follow_remote_head == 1 && verbosity >= 0) > > And there is one more. > >> diff --git a/remote.c b/remote.c >> index 10104d11e3..5a768ddac2 100644 >> --- a/remote.c >> +++ b/remote.c >> @@ -514,6 +514,15 @@ static int handle_config(const char *key, const char *value, >> } else if (!strcmp(subkey, "serveroption")) { >> return parse_transport_option(key, value, >> &remote->server_options); >> + } else if (!strcmp(subkey, "followremotehead")) { >> + if (!strcmp(value, "never")) >> + remote->follow_remote_head = -1; >> + else if (!strcmp(value, "create")) >> + remote->follow_remote_head = 0; >> + else if (!strcmp(value, "warn")) >> + remote->follow_remote_head = 1; >> + else if (!strcmp(value, "always")) >> + remote->follow_remote_head = 2; > > Use something like > > /* The setting for whether to update HEAD for the remote. */ > enum follow_remote_head { > FOLLOW_REMOTE_NEVER = -1, > FOLLOW_REMOTE_CREATE = 0, > FOLLOW_REMOTE_WARN = 1, > FOLLOW_REMOTE_ALWAYS = 2, > }; > > or something? I have no strong preference between "enum" and > "#define" myself, but moderately strong preference for anything > symbolic over magic numbers. Ah, my mistake sorry. Magic number bad. Best, Bence