Git development
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: Kristofer Karlsson via GitGitGadget <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org, Kristofer Karlsson <krka@spotify.com>
Subject: Re: [PATCH v2 1/2] Documentation: describe connectivity checking
Date: Mon, 5 Oct 2026 09:59:41 +0200	[thread overview]
Message-ID: <asNY7SfEohsOSf0J@pks.im> (raw)
In-Reply-To: <97c11449aeae924436ba22a00a2545254e988a58.1790600552.git.gitgitgadget@gmail.com>

On Mon, Sep 28, 2026 at 01:02:31PM +0000, Kristofer Karlsson via GitGitGadget wrote:
> diff --git a/Documentation/technical/connectivity-check.adoc b/Documentation/technical/connectivity-check.adoc
> new file mode 100644
> index 0000000000..d20bff6af6
> --- /dev/null
> +++ b/Documentation/technical/connectivity-check.adoc
> @@ -0,0 +1,109 @@
> +Connectivity checking
> +=====================
> +
> +After receiving new objects via fetch, push (receive-pack), clone,
> +or bundle, Git verifies that the new reference tips do not leave
> +the repository in a state where reachable objects are missing.
> +This verification is called the connectivity check.
> +
> +Connectivity invariant
> +----------------------
> +
> +A repository is connected when every object reachable from its
> +references is available locally (with exceptions noted below).

Right. I think it would also be important to spell out the reverse of
this, which is that nothing can be assumed about objects that aren't
reachable by any reference. So even if an object already exists in the
object database, it is not safe to assume that it is fully connected
unless it is referenced.

> +The connectivity check maintains this invariant when references
> +are updated.  It trusts the existing connected state and verifies

Nit: it's basically already implicit, but I'd clarify that "existing
connected state" is again just the connected state of objects reachable
from reference tips. So maybe "It trusts that all objects reachable from
references are already fully connected and verifies..."

> +that the new reference tips do not introduce references to
> +unavailable objects.  Verification is permitted to stop when it
> +reaches objects already reachable from trusted existing
> +references, since their closure is already connected.  These
> +trusted references include local references and references from
> +alternate object stores.
> +
> +Without this check, a truncated or corrupted transfer could leave
> +a repository in a state where later history walks encounter
> +missing objects.
> +
> +Exceptions
> +~~~~~~~~~~
> +
> +Gitlink entries (submodule references) are excluded from
> +connectivity checking.  Their target objects belong to a separate
> +repository.
> +
> +In partial clones, objects promised by a promisor remote are
> +accepted as connected without requiring local existence.  The
> +check excludes promisor objects from traversal so that it does
> +not trigger on-demand fetches for them.
> +
> +Full connectivity check
> +-----------------------
> +
> +`check_connected()` (see `connected.c`) normally performs the

I'm always a bit hesitant to directly refer to code in our docs. We
should either make this documentation part of "connected.c" directly, or
we should not refer to code. Otherwise, chances that this documentation
grows stale is very high.

> +connectivity check using a `rev-list` subprocess, feeding the
> +new reference tips via stdin.  A normal invocation is roughly:
> +
> +    git rev-list --objects --stdin --not --all --quiet
> +        --alternate-refs [--exclude-promisor-objects]
> +
> +When promisor remotes are configured, `check_connected()` first
> +attempts a fast path based on promisor packfiles.  If it falls
> +back to the `rev-list` check, `--exclude-promisor-objects` is
> +added so that the traversal does not trigger on-demand fetches.
> +
> +Consider the following graph after a fetch, where all reference
> +tips point directly to commits.  For simplicity, only local
> +references appear on the already-connected side; alternate refs
> +play the same role.  N3 is a merge commit:
> +
> +            /-------------L2
> +           /
> +    C1---B1---C2---B2-----L1
> +          \         \
> +           N1        N3---T2
> +            \       /
> +             N2-----------T1
> +
> +    L1, L2:         local refs
> +    T1, T2:         incoming tips (new refs)
> +    N1, N2, N3:     incoming commits (N3 is a merge)
> +    B1, B2:         boundary commits (already connected)
> +    C1, C2:         already connected (but not boundary)
> +
> +The incoming set is the commits reachable from the incoming
> +tips but not from the already-connected side.  Boundary commits
> +are the already-connected commits at the edge of that set.  Here
> +B1 is an ancestor of B2, which happens when incoming branches
> +fork at different depths in the existing history.
> +
> +The check proceeds in three phases:
> +
> +1. Walk from the incoming tips (T1, T2) against the trusted
> +   refs (L1, L2) to find the incoming set ({N1, N2, N3, T1, T2}).
> +
> +2. Walk the trees of the boundary commits (B1, B2) and mark
> +   those objects uninteresting.  These trees are already trusted
> +   because their commits are on the already-connected side.
> +
> +3. Walk the trees of each incoming commit and verify that every
> +   referenced object is connected, stopping at objects already
> +   marked uninteresting in phase 2.

I feel like these phases here basically just explain how revision walks
work without adding any more details that are specifically relevant to
the connectivity check.

> +Deepening fetches
> +~~~~~~~~~~~~~~~~~
> +
> +For deepening fetches (where the shallow boundary moves), the
> +full check omits `--not --all`.  There is no existing-reference
> +boundary at which the walk can stop.  Instead, traversal follows
> +the effective shallow boundary supplied for the deepened
> +repository.  The new content may be below the old shallow
> +boundary even when the tips themselves have not changed.
> +
> +Non-commit tips
> +~~~~~~~~~~~~~~~
> +
> +When a new reference points to a non-commit object, such as a
> +tag, tree, or blob, that object is not part of the commit walk.
> +These non-commit tips are handled by the subsequent object
> +traversal.

Huh, what subsequent object traversal? This part puzzles me a bit.

Patrick

  reply	other threads:[~2026-10-05  7:59 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14  9:47 [PATCH 0/2] connected: add incremental connectivity check Kristofer Karlsson via GitGitGadget
2026-09-14  9:47 ` [PATCH 1/2] Documentation: describe connectivity checking Kristofer Karlsson via GitGitGadget
2026-09-14  9:47 ` [PATCH 2/2] connected: add incremental connectivity check via rev-list Kristofer Karlsson via GitGitGadget
2026-09-14 15:26   ` Junio C Hamano
2026-09-14 17:46     ` Kristofer Karlsson
2026-09-14 15:12 ` [PATCH 0/2] connected: add incremental connectivity check Junio C Hamano
2026-09-28 13:02 ` [PATCH v2 " Kristofer Karlsson via GitGitGadget
2026-09-28 13:02   ` [PATCH v2 1/2] Documentation: describe connectivity checking Kristofer Karlsson via GitGitGadget
2026-10-05  7:59     ` Patrick Steinhardt [this message]
2026-10-05 19:17       ` Junio C Hamano
2026-10-06  5:59         ` Patrick Steinhardt
2026-10-06 10:03           ` Kristofer Karlsson
2026-10-06 10:12       ` Kristofer Karlsson
2026-09-28 13:02   ` [PATCH v2 2/2] connected: add incremental connectivity check via rev-list Kristofer Karlsson via GitGitGadget
2026-10-05  8:00     ` Patrick Steinhardt
2026-10-06 10:37       ` Kristofer Karlsson
2026-10-06 12:08         ` Patrick Steinhardt
2026-10-06 12:36           ` Kristofer Karlsson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=asNY7SfEohsOSf0J@pks.im \
    --to=ps@pks.im \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=krka@spotify.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox