diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc index 25fe219d10..91e46f66f5 100644 --- a/Documentation/config/remote.adoc +++ b/Documentation/config/remote.adoc @@ -108,7 +108,8 @@ the values inherited from a lower priority configuration files (e.g. `$HOME/.gitconfig`). remote..followRemoteHEAD:: - How linkgit:git-fetch[1] should handle updates to `remotes//HEAD`. + How linkgit:git-fetch[1] should handle updates to `remotes//HEAD` + when fetching using the configured refspecs of a remote. The default value is "create", which will create `remotes//HEAD` if it exists on the remote, but not locally; this will not touch an already existing local reference. Setting it to "warn" will print diff --git a/builtin/fetch.c b/builtin/fetch.c index 02af505469..66f5ae31b6 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1691,21 +1691,6 @@ cleanup: return result; } -static int uses_remote_tracking(struct transport *transport, struct refspec *rs) -{ - if (!remote_is_configured(transport->remote, 0)) - return 0; - - if (!rs->nr) - rs = &transport->remote->fetch; - - for (int i = 0; i < rs->nr; i++) - if (rs->items[i].dst) - return 1; - - return 0; -} - static int do_fetch(struct transport *transport, struct refspec *rs, const struct fetch_config *config) @@ -1720,6 +1705,7 @@ static int do_fetch(struct transport *transport, TRANSPORT_LS_REFS_OPTIONS_INIT; struct fetch_head fetch_head = { 0 }; struct strbuf err = STRBUF_INIT; + int do_set_head = 0; if (tags == TAGS_DEFAULT) { if (transport->remote->fetch_tags == 2) @@ -1740,9 +1726,11 @@ static int do_fetch(struct transport *transport, } else { struct branch *branch = branch_get(NULL); - if (transport->remote->fetch.nr) + if (transport->remote->fetch.nr) { refspec_ref_prefixes(&transport->remote->fetch, &transport_ls_refs_options.ref_prefixes); + do_set_head = 1; + } if (branch_has_merge_config(branch) && !strcmp(branch->remote_name, transport->remote->name)) { int i; @@ -1765,8 +1753,7 @@ static int do_fetch(struct transport *transport, strvec_push(&transport_ls_refs_options.ref_prefixes, "refs/tags/"); - if (transport_ls_refs_options.ref_prefixes.nr && - uses_remote_tracking(transport, rs)) + if (do_set_head) strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); @@ -1918,7 +1905,7 @@ 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)) + if (do_set_head && set_head(remote_refs, transport->remote)) ; /* * Way too many cases where this can go wrong diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index bb7e0c6879..fed5823e85 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -499,7 +499,7 @@ test_expect_success 'set-head --auto has no problem w/multiple HEADs' ' cd test && git fetch two "refs/heads/*:refs/remotes/two/*" && git remote set-head --auto two >output 2>&1 && - echo "${SQ}two/HEAD${SQ} is unchanged and points to ${SQ}main${SQ}" >expect && + echo "${SQ}two/HEAD${SQ} is now created and points to ${SQ}main${SQ}" >expect && test_cmp expect output ) ' diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 5f350facf5..ad23dd11ef 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -250,6 +250,20 @@ test_expect_success "fetch test followRemoteHEAD always" ' ) ' +test_expect_success 'followRemoteHEAD does not kick in with refspecs' ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git remote set-head origin other && + git config set remote.origin.followRemoteHEAD always && + git fetch origin refs/heads/main:refs/remotes/origin/main && + echo refs/remotes/origin/other >expect && + git symbolic-ref refs/remotes/origin/HEAD >actual && + test_cmp expect actual + ) +' + test_expect_success 'fetch --prune on its own works as expected' ' cd "$D" && git clone . prune &&