Skip to content

Commit 49ca2fb

Browse files
peffgitster
authored andcommitted
fetch: add branch.*.merge to default ref-prefix extension
When running "git pull" with no arguments, we'll do a default "git fetch" and then try to merge the branch specified by the branch.*.merge config. There's code in get_ref_map() to treat that "merge" branch as something we want to fetch, even if it is not otherwise covered by the default refspec. This works fine with the v0 protocol, as the server tells us about all of the refs, and get_ref_map() is the ultimate decider of what we fetch. But in the v2 protocol, we send the ref-prefix extension to the server, asking it to limit the ref advertisement. And we only tell it about the default refspec for the remote; we don't mention the branch.*.merge config at all. This usually doesn't matter, because the default refspec matches "refs/heads/*", which covers all branches. But if you explicitly use a narrow refspec, then "git pull" on some branches may fail. The server doesn't advertise the branch, so we don't fetch it, and "git pull" thinks that it went away upstream. We can fix this by including any branch.*.merge entries for the current branch in the list of ref-prefixes we pass to the server. This only needs to happen when using the default configured refspec (since command-line refspecs are already added, and take precedence in deciding what we fetch). We don't otherwise need to replicate any of the "what to fetch" logic in get_ref_map(). These ref-prefixes are an optimization, so it's OK if we tell the server to advertise the branch.*.merge ref, even if we're not going to pull it. We'll just choose not to fetch it. The test here is based on one constructed by Johannes. I modified the branch names to trigger the ref-prefix issue (and be more descriptive), and to confirm that "git pull" actually updated the local ref, which should be more robust than just checking stderr. Reported-by: Lana Deere <[email protected]> Helped-by: Johannes Schindelin <[email protected]> Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 080bc49 commit 49ca2fb

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

builtin/fetch.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,9 +1626,21 @@ static int do_fetch(struct transport *transport,
16261626
break;
16271627
}
16281628
}
1629-
} else if (transport->remote->fetch.nr)
1630-
refspec_ref_prefixes(&transport->remote->fetch,
1631-
&transport_ls_refs_options.ref_prefixes);
1629+
} else {
1630+
struct branch *branch = branch_get(NULL);
1631+
1632+
if (transport->remote->fetch.nr)
1633+
refspec_ref_prefixes(&transport->remote->fetch,
1634+
&transport_ls_refs_options.ref_prefixes);
1635+
if (branch_has_merge_config(branch) &&
1636+
!strcmp(branch->remote_name, transport->remote->name)) {
1637+
int i;
1638+
for (i = 0; i < branch->merge_nr; i++) {
1639+
strvec_push(&transport_ls_refs_options.ref_prefixes,
1640+
branch->merge[i]->src);
1641+
}
1642+
}
1643+
}
16321644

16331645
if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
16341646
must_list_refs = 1;

t/t5520-pull.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,23 @@ test_expect_success 'fail if upstream branch does not exist' '
218218
test_cmp expect file
219219
'
220220

221+
test_expect_success 'fetch upstream branch even if refspec excludes it' '
222+
# the branch names are not important here except that
223+
# the first one must not be a prefix of the second,
224+
# since otherwise the ref-prefix protocol extension
225+
# would match both
226+
git branch in-refspec HEAD^ &&
227+
git branch not-in-refspec HEAD &&
228+
git init -b in-refspec downstream &&
229+
git -C downstream remote add -t in-refspec origin "file://$(pwd)/.git" &&
230+
git -C downstream config branch.in-refspec.remote origin &&
231+
git -C downstream config branch.in-refspec.merge refs/heads/not-in-refspec &&
232+
git -C downstream pull &&
233+
git rev-parse --verify not-in-refspec >expect &&
234+
git -C downstream rev-parse --verify HEAD >actual &&
235+
test_cmp expect actual
236+
'
237+
221238
test_expect_success 'fail if the index has unresolved entries' '
222239
git checkout -b third second^ &&
223240
test_when_finished "git checkout -f copy && git branch -D third" &&

0 commit comments

Comments
 (0)