Skip to content

Commit b45113f

Browse files
committed
Merge branch 'jk/fetch-follow-remote-head-fix'
"git fetch [<remote>]" with only the configured fetch refspec should be the only thing to update refs/remotes/<remote>/HEAD, but the code was overly eager to do so in other cases. * jk/fetch-follow-remote-head-fix: fetch: make set_head() call easier to read fetch: don't ask for remote HEAD if followRemoteHEAD is "never" fetch: only respect followRemoteHEAD with configured refspecs
2 parents c152ae3 + f9356f9 commit b45113f

File tree

4 files changed

+32
-28
lines changed

4 files changed

+32
-28
lines changed

Documentation/config/remote.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ the values inherited from a lower priority configuration files (e.g.
108108
`$HOME/.gitconfig`).
109109

110110
remote.<name>.followRemoteHEAD::
111-
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`.
111+
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`
112+
when fetching using the configured refspecs of a remote.
112113
The default value is "create", which will create `remotes/<name>/HEAD`
113114
if it exists on the remote, but not locally; this will not touch an
114115
already existing local reference. Setting it to "warn" will print

builtin/fetch.c

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,9 +1643,6 @@ static int set_head(const struct ref *remote_refs, struct remote *remote)
16431643
string_list_append(&heads, strip_refshead(ref->name));
16441644
}
16451645

1646-
if (follow_remote_head == FOLLOW_REMOTE_NEVER)
1647-
goto cleanup;
1648-
16491646
if (!heads.nr)
16501647
result = 1;
16511648
else if (heads.nr > 1)
@@ -1691,21 +1688,6 @@ static int set_head(const struct ref *remote_refs, struct remote *remote)
16911688
return result;
16921689
}
16931690

1694-
static int uses_remote_tracking(struct transport *transport, struct refspec *rs)
1695-
{
1696-
if (!remote_is_configured(transport->remote, 0))
1697-
return 0;
1698-
1699-
if (!rs->nr)
1700-
rs = &transport->remote->fetch;
1701-
1702-
for (int i = 0; i < rs->nr; i++)
1703-
if (rs->items[i].dst)
1704-
return 1;
1705-
1706-
return 0;
1707-
}
1708-
17091691
static int do_fetch(struct transport *transport,
17101692
struct refspec *rs,
17111693
const struct fetch_config *config)
@@ -1720,6 +1702,7 @@ static int do_fetch(struct transport *transport,
17201702
TRANSPORT_LS_REFS_OPTIONS_INIT;
17211703
struct fetch_head fetch_head = { 0 };
17221704
struct strbuf err = STRBUF_INIT;
1705+
int do_set_head = 0;
17231706

17241707
if (tags == TAGS_DEFAULT) {
17251708
if (transport->remote->fetch_tags == 2)
@@ -1740,9 +1723,12 @@ static int do_fetch(struct transport *transport,
17401723
} else {
17411724
struct branch *branch = branch_get(NULL);
17421725

1743-
if (transport->remote->fetch.nr)
1726+
if (transport->remote->fetch.nr) {
17441727
refspec_ref_prefixes(&transport->remote->fetch,
17451728
&transport_ls_refs_options.ref_prefixes);
1729+
if (transport->remote->follow_remote_head != FOLLOW_REMOTE_NEVER)
1730+
do_set_head = 1;
1731+
}
17461732
if (branch_has_merge_config(branch) &&
17471733
!strcmp(branch->remote_name, transport->remote->name)) {
17481734
int i;
@@ -1765,8 +1751,7 @@ static int do_fetch(struct transport *transport,
17651751
strvec_push(&transport_ls_refs_options.ref_prefixes,
17661752
"refs/tags/");
17671753

1768-
if (transport_ls_refs_options.ref_prefixes.nr &&
1769-
uses_remote_tracking(transport, rs))
1754+
if (do_set_head)
17701755
strvec_push(&transport_ls_refs_options.ref_prefixes,
17711756
"HEAD");
17721757

@@ -1925,12 +1910,13 @@ static int do_fetch(struct transport *transport,
19251910
"you need to specify exactly one branch with the --set-upstream option"));
19261911
}
19271912
}
1928-
if (set_head(remote_refs, transport->remote))
1929-
;
1913+
if (do_set_head) {
19301914
/*
1931-
* Way too many cases where this can go wrong
1932-
* so let's just fail silently for now.
1915+
* Way too many cases where this can go wrong so let's just
1916+
* ignore errors and fail silently for now.
19331917
*/
1918+
set_head(remote_refs, transport->remote);
1919+
}
19341920

19351921
cleanup:
19361922
if (retcode) {

t/t5505-remote.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ test_expect_success 'set-head --auto has no problem w/multiple HEADs' '
499499
cd test &&
500500
git fetch two "refs/heads/*:refs/remotes/two/*" &&
501501
git remote set-head --auto two >output 2>&1 &&
502-
echo "${SQ}two/HEAD${SQ} is unchanged and points to ${SQ}main${SQ}" >expect &&
502+
echo "${SQ}two/HEAD${SQ} is now created and points to ${SQ}main${SQ}" >expect &&
503503
test_cmp expect output
504504
)
505505
'

t/t5510-fetch.sh

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ test_expect_success "fetch test followRemoteHEAD never" '
125125
cd two &&
126126
git update-ref --no-deref -d refs/remotes/origin/HEAD &&
127127
git config set remote.origin.followRemoteHEAD "never" &&
128-
git fetch &&
128+
GIT_TRACE_PACKET=$PWD/trace.out git fetch &&
129+
# Confirm that we do not even ask for HEAD when we are
130+
# not going to act on it.
131+
test_grep ! "ref-prefix HEAD" trace.out &&
129132
test_must_fail git rev-parse --verify refs/remotes/origin/HEAD
130133
)
131134
'
@@ -256,6 +259,20 @@ test_expect_success "fetch test followRemoteHEAD always" '
256259
)
257260
'
258261

262+
test_expect_success 'followRemoteHEAD does not kick in with refspecs' '
263+
test_when_finished "git config unset remote.origin.followRemoteHEAD" &&
264+
(
265+
cd "$D" &&
266+
cd two &&
267+
git remote set-head origin other &&
268+
git config set remote.origin.followRemoteHEAD always &&
269+
git fetch origin refs/heads/main:refs/remotes/origin/main &&
270+
echo refs/remotes/origin/other >expect &&
271+
git symbolic-ref refs/remotes/origin/HEAD >actual &&
272+
test_cmp expect actual
273+
)
274+
'
275+
259276
test_expect_success 'fetch --prune on its own works as expected' '
260277
cd "$D" &&
261278
git clone . prune &&

0 commit comments

Comments
 (0)