[PATCH 1/2] Documentation: describe connectivity checking
- From
Kristofer Karlsson via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Sep 14, 2026, 09:47 UTC
- Message-ID
- <e55c5452db0b7cb683d4e2ad51cd8f44046c23bd.1789379276.git.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2211.git.1789379276.gitgitgadget@gmail.com>
From: Kristofer Karlsson <krka@spotify.com>
Add Documentation/technical/connectivity-check.adoc describing the connectivity invariant and the full connectivity check.
Signed-off-by: Kristofer Karlsson <krka@spotify.com> --- .../technical/connectivity-check.adoc | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 Documentation/technical/connectivity-check.adoc
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). + +The connectivity check maintains this invariant when references +are updated. It trusts the existing connected state 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 +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. + +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.
-- gitgitgadget