diff --git a/Documentation/rev-list-options.adoc b/Documentation/rev-list-options.adoc index eaee6ee8399c57..6df0e536ad7ce6 100644 --- a/Documentation/rev-list-options.adoc +++ b/Documentation/rev-list-options.adoc @@ -223,9 +223,10 @@ explicitly. Pretend as if all objects mentioned as ref tips of alternate repositories were listed on the command line. An alternate repository is any repository whose object directory is specified - in `objects/info/alternates`. The set of included objects may - be modified by `core.alternateRefsCommand`, etc. See - linkgit:git-config[1]. + in `objects/info/alternates`. The refs of shallow and grafted + alternate repositories are ignored, as the history behind them + may be missing. The set of included objects may be modified by + `core.alternateRefsCommand`, etc. See linkgit:git-config[1]. `--single-worktree`:: By default, all working trees will be examined by the diff --git a/connected.c b/connected.c index 7e269768327238..cf2647c94244b6 100644 --- a/connected.c +++ b/connected.c @@ -91,15 +91,17 @@ int check_connected(oid_iterate_fn fn, void *cb_data, strvec_push(&rev_list.args, "--stdin"); if (repo_has_promisor_remote(the_repository)) strvec_push(&rev_list.args, "--exclude-promisor-objects"); + + /* define where the traversal should stop */ + strvec_push(&rev_list.args, "--not"); if (!opt->is_deepening_fetch) { - strvec_push(&rev_list.args, "--not"); if (opt->exclude_hidden_refs_section) strvec_pushf(&rev_list.args, "--exclude-hidden=%s", opt->exclude_hidden_refs_section); strvec_push(&rev_list.args, "--all"); } - strvec_push(&rev_list.args, "--quiet"); strvec_push(&rev_list.args, "--alternate-refs"); + strvec_push(&rev_list.args, "--quiet"); if (opt->progress) strvec_pushf(&rev_list.args, "--progress=%s", _("Checking connectivity")); diff --git a/odb.c b/odb.c index 7d555be09feaea..e431bcb84c80ed 100644 --- a/odb.c +++ b/odb.c @@ -453,6 +453,17 @@ static int refs_from_alternate_cb(struct odb_source *alternate, goto out; strbuf_setlen(&path, base_len); + /* A shallow or grafted repository may lack the history behind its refs. */ + strbuf_addstr(&path, "/shallow"); + if (!access(path.buf, F_OK)) + goto out; + strbuf_setlen(&path, base_len); + + strbuf_addstr(&path, "/info/grafts"); + if (!access(path.buf, F_OK)) + goto out; + strbuf_setlen(&path, base_len); + read_alternate_refs(alternate->odb->repo, path.buf, cb->fn, cb->payload); out: diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh index 2fb6d549d394ee..9c3862709a6d08 100755 --- a/t/t5618-alternate-refs.sh +++ b/t/t5618-alternate-refs.sh @@ -58,4 +58,29 @@ test_expect_success 'log --source shows .alternate marker' ' test_cmp expect actual ' +test_expect_success 'connectivity check of a fetch excludes alternate refs' ' + GIT_TRACE2_EVENT="$PWD/fetch.trace" git fetch origin && + test_subcommand_flex git rev-list --objects --stdin --not --all \ + --alternate-refs --quiet shallow-tip && + cp .git/objects/info/alternates alternates.bak && + test_when_finished "mv alternates.bak .git/objects/info/alternates" && + echo "$TRASH_DIRECTORY/shallow/.git/objects" >>.git/objects/info/alternates && + git cat-file -e $(cat shallow-tip) && + git rev-list --remotes=origin >expect && + git rev-list --alternate-refs >actual && + test_cmp expect actual +' + test_done