]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch set_head: add warn-if-not-$branch option
authorBence Ferdinandy <bence@ferdinandy.com>
Thu, 5 Dec 2024 12:16:21 +0000 (13:16 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Dec 2024 17:59:40 +0000 (02:59 +0900)
Currently if we want to have a remote/HEAD locally that is different
from the one on the remote, but we still want to get a warning if remote
changes HEAD, our only option is to have an indiscriminate warning with
"follow_remote_head" set to "warn". Add a new option
"warn-if-not-$branch", where $branch is a branch name we do not wish to
get a warning about. If the remote HEAD is $branch do not warn,
otherwise, behave as "warn".

E.g. let's assume, that our remote origin has HEAD
set to "master", but locally we have "git remote set-head origin seen".
Setting 'remote.origin.followRemoteHEAD = "warn"' will always print
a warning, even though the remote has not changed HEAD from "master".
Setting 'remote.origin.followRemoteHEAD = "warn-if-not-master" will
squelch the warning message, unless the remote changes HEAD from
"master". Note, that should the remote change HEAD to "seen" (which we
have locally), there will still be no warning.

Improve the advice message in report_set_head to also include silencing
the warning message with "warn-if-not-$branch".

Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config/remote.txt
builtin/fetch.c
remote.c
remote.h
t/t5510-fetch.sh

index 024f92befcc540b4458f8d6c03d9ebcfd414cc5f..4118c219c13ac6ba7bd624fad0764e498f6537b7 100644 (file)
@@ -106,10 +106,12 @@ remote.<name>.followRemoteHEAD::
        How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`.
        The default value is "create", which will create `remotes/<name>/HEAD`
        if it exists on the remote, but not locally, but will not touch an
-       already existing local reference.  Setting to "warn" will print
+       already existing local reference. Setting to "warn" will print
        a message if the remote has a different value, than the local one and
-       in case there is no local reference, it behaves like "create". Setting
-       to "always" will silently update it to the value on the remote.
+       in case there is no local reference, it behaves like "create".
+       A variant on "warn" is "warn-if-not-$branch", which behaves like
+       "warn", but if `HEAD` on the remote is `$branch` it will be silent.
+       Setting to "always" will silently update it to the value on the remote.
        Finally, setting it to "never" will never change or create the local
        reference.
 +
index 897e71325fef3dee4d63e448264c8fb12e881757..c4257a7ead740d3adb703bd4b02b6162e922d764 100644 (file)
@@ -1584,10 +1584,12 @@ static void set_head_advice_msg(const char *remote, const char *head_name)
        const char message_advice_set_head[] =
        N_("Run 'git remote set-head %s %s' to follow the change, or set\n"
           "'remote.%s.followRemoteHEAD' configuration option to a different value\n"
-          "if you do not want to see this message.");
+          "if you do not want to see this message. Specifically running\n"
+          "'git config set remote.%s.followRemoteHEAD %s' will disable the warning\n"
+          "until the remote changes HEAD to something else.");
 
        advise_if_enabled(ADVICE_FETCH_SET_HEAD_WARN, _(message_advice_set_head),
-                       remote, head_name, remote);
+                       remote, head_name, remote, remote, head_name);
 }
 
 static void report_set_head(const char *remote, const char *head_name,
@@ -1612,7 +1614,8 @@ static void report_set_head(const char *remote, const char *head_name,
        strbuf_release(&buf_prefix);
 }
 
-static int set_head(const struct ref *remote_refs, int follow_remote_head)
+static int set_head(const struct ref *remote_refs, int follow_remote_head,
+               const char *no_warn_branch)
 {
        int result = 0, create_only, is_bare, was_detached;
        struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
@@ -1669,7 +1672,9 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head)
                result = 1;
                goto cleanup;
        }
-       if (follow_remote_head == FOLLOW_REMOTE_WARN && verbosity >= 0)
+       if (verbosity >= 0 &&
+               follow_remote_head == FOLLOW_REMOTE_WARN &&
+               (!no_warn_branch || strcmp(no_warn_branch, head_name)))
                report_set_head(remote, head_name, &b_local_head, was_detached);
 
 cleanup:
@@ -1898,7 +1903,8 @@ static int do_fetch(struct transport *transport,
                                  "you need to specify exactly one branch with the --set-upstream option"));
                }
        }
-       if (set_head(remote_refs, transport->remote->follow_remote_head))
+       if (set_head(remote_refs, transport->remote->follow_remote_head,
+               transport->remote->no_warn_branch))
                ;
                /*
                 * Way too many cases where this can go wrong
index 0b18840d4360be7c69c6b0174cff5a969d88c5a7..4ec5d3f47b931db675bb2917632caebd4151b893 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -515,14 +515,23 @@ static int handle_config(const char *key, const char *value,
                return parse_transport_option(key, value,
                                              &remote->server_options);
        } else if (!strcmp(subkey, "followremotehead")) {
+               const char *no_warn_branch;
                if (!strcmp(value, "never"))
                        remote->follow_remote_head = FOLLOW_REMOTE_NEVER;
                else if (!strcmp(value, "create"))
                        remote->follow_remote_head = FOLLOW_REMOTE_CREATE;
-               else if (!strcmp(value, "warn"))
+               else if (!strcmp(value, "warn")) {
                        remote->follow_remote_head = FOLLOW_REMOTE_WARN;
-               else if (!strcmp(value, "always"))
+                       remote->no_warn_branch = NULL;
+               } else if (skip_prefix(value, "warn-if-not-", &no_warn_branch)) {
+                       remote->follow_remote_head = FOLLOW_REMOTE_WARN;
+                       remote->no_warn_branch = no_warn_branch;
+               } else if (!strcmp(value, "always")) {
                        remote->follow_remote_head = FOLLOW_REMOTE_ALWAYS;
+               } else {
+                       warning(_("unrecognized followRemoteHEAD value '%s' ignored"),
+                               value);
+               }
        }
        return 0;
 }
index 184b35653d092a1751a5a0622ef2d1613723515c..bda10dd5c85ffd8988a6c3d39583e7b9701278b8 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -116,6 +116,7 @@ struct remote {
        struct string_list server_options;
 
        enum follow_remote_head_settings follow_remote_head;
+       const char *no_warn_branch;
 };
 
 /**
index 5c96591b9e83247bb2ad1db34b3e05d14a7769cb..13881603f69e8e661851ed2b9923e8404f9c6577 100755 (executable)
@@ -182,6 +182,44 @@ test_expect_success "fetch test followRemoteHEAD warn quiet" '
        )
 '
 
+test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is same" '
+       test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
+       (
+               cd "$D" &&
+               cd two &&
+               git rev-parse --verify refs/remotes/origin/other &&
+               git remote set-head origin other &&
+               git rev-parse --verify refs/remotes/origin/HEAD &&
+               git rev-parse --verify refs/remotes/origin/main &&
+               git config set remote.origin.followRemoteHEAD "warn-if-not-main" &&
+               actual=$(git fetch) &&
+               test "z" = "z$actual" &&
+               head=$(git rev-parse refs/remotes/origin/HEAD) &&
+               branch=$(git rev-parse refs/remotes/origin/other) &&
+               test "z$head" = "z$branch"
+       )
+'
+
+test_expect_success "fetch test followRemoteHEAD warn-if-not-branch branch is different" '
+       test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
+       (
+               cd "$D" &&
+               cd two &&
+               git rev-parse --verify refs/remotes/origin/other &&
+               git remote set-head origin other &&
+               git rev-parse --verify refs/remotes/origin/HEAD &&
+               git rev-parse --verify refs/remotes/origin/main &&
+               git config set remote.origin.followRemoteHEAD "warn-if-not-some/different-branch" &&
+               git fetch >actual &&
+               echo "${SQ}HEAD${SQ} at ${SQ}origin${SQ} is ${SQ}main${SQ}," \
+                       "but we have ${SQ}other${SQ} locally." >expect &&
+               test_cmp expect actual &&
+               head=$(git rev-parse refs/remotes/origin/HEAD) &&
+               branch=$(git rev-parse refs/remotes/origin/other) &&
+               test "z$head" = "z$branch"
+       )
+'
+
 test_expect_success "fetch test followRemoteHEAD always" '
        test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
        (