Merge branch 'kn/fetch-tag-backfill-batch-fix' into seen

When 'git fetch' uses batched reference updates, references are not
committed before backfilling tags, causing shallow fetches to report
no local references during negotiation and receive all objects from
the server again.  The batched update is now committed before tag
backfilling begins.

* kn/fetch-tag-backfill-batch-fix:
  fetch: commit references fetched before backfilling tags
seen
Junio C Hamano 2026-10-12 14:23:53 -07:00
commit c64409ac5b
2 changed files with 37 additions and 0 deletions

View File

@ -2200,6 +2200,27 @@ static int do_fetch(struct transport *transport,
struct ref *tags_ref_map = NULL, **tail = &tags_ref_map;

find_non_local_tags(remote_refs, transaction, &tags_ref_map, &tail);

/*
* Backfilling tags has no depth limit. If we don't commit
* the fetched references, the backfill will report no refs
* in the 'have' section of the negotiation. This can cause
* the server to send all objects.
*/
if (tags_ref_map && !atomic_fetch) {
retcode |= commit_ref_transaction(&transaction, false,
transport->remote->name,
&rejected_refs, &err);

transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
REF_TRANSACTION_ALLOW_FAILURE, &err);
if (!transaction) {
free_refs(tags_ref_map);
retcode = -1;
goto cleanup;
}
}

if (tags_ref_map) {
/*
* If backfilling of tags fails then we want to tell

View File

@ -2108,6 +2108,22 @@ test_expect_success "backfill tags when providing a refspec" '
test_cmp expect actual
'

test_expect_success 'shallow fetch does not fetch objects again for tags' '
test_when_finished rm -rf source target &&

git init source &&
test_commit_bulk -C source 10 &&
git -C source tag -a tag -m tag HEAD~2 &&
root_oid=$(git -C source rev-parse HEAD~9) &&

git init target &&
git -C target remote add origin ../source &&
git -C target fetch --depth 5 origin &&

# Should not fetch objects beyond the pre-specified depth.
test_must_fail git -C target cat-file -e "$root_oid"
'

test_expect_success REFFILES "FETCH_HEAD is updated even if ref updates fail" '
test_when_finished rm -rf base repo &&