Files
Kristofer Karlsson 656be5948a connected: add "auto" connectivity check mode
The incremental connectivity check pays a per-commit cost.  For
every incoming commit it reads the new trees along the changed
paths, and the trees at the same paths in its parents to compare
against.  A parent tree is often read again even though an earlier
commit already read it: on git.git, about a third of the tree reads
for 2000 incoming commits are such re-reads.  The full check
instead pays a mostly fixed cost for walking the boundary trees,
so with many incoming commits the incremental check becomes the
slower one (see the previous commit).  Users who mostly
receive small pushes but occasionally a large one should not have
to choose between the two.

Add an "auto" value for transfer.connectivityCheck that picks the
mode based on the incoming history.  When the revision walk is
limited, which is the case whenever the receiving repository has
references, the incoming commit list is already computed by
limit_list(), so counting it is cheap.  "auto" then uses the
incremental check for up to 1000 incoming commits, and the full
check above that.

The cutoff is a fixed constant based on the p5413 fixture in the
previous commit, where breakeven is between 500 and 3000 commits.
It is conservative for repositories with large trees, where the
fixed cost of the full check is higher.  Measured on real
repositories (rev-list against a single boundary commit, mean
of at least 10 runs):

    repository   files  commits    full  incr.  full/incr
    internal A    556K     1000   1.71s  0.61s    2.8x
    internal A    556K     4000   2.78s  2.83s    1.0x
    internal B    288K     1000   1.78s  0.88s    2.0x
    linux          95K      598   0.33s  0.12s    2.7x
    linux          95K     1728   0.56s  0.35s    1.6x
    git           4.9K      984   0.22s  0.27s    0.8x

With small trees incremental can be slower within the cutoff,
but both modes are fast enough there (0.22s vs 0.27s for git
above) that the difference does not matter in practice.

No single cutoff is optimal for every repository, so it can be set
with "auto=<cutoff>"; plain "auto" uses 1000.  A malformed cutoff
is treated like any other unknown value: it falls back to "full"
with a warning.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-10-23 08:32:30 -07:00

158 lines
7.3 KiB
Plaintext

transfer.connectivityCheck::
Choose which algorithm to use for the connectivity check
performed during object transfer operations such as
linkgit:git-fetch[1] and linkgit:git-receive-pack[1].
The connectivity check verifies that all objects reachable
from the incoming tips are available locally or, in a partial
clone, promised by a promisor remote.
The variants are as follows:
+
--
`full` (default);;
Walk the full object closure of the boundary commits.
`incremental`;;
Verify incoming commits by diffing their trees against parent
trees, recursively descending only into entries that differ.
The largest benefits occur when incoming commits change a
small fraction of a large tree closure, and it can be slower
than `full` when there are many incoming commits.
Falls back to `full` for clones, pushes into an empty
repository and deepening fetches.
`auto`;;
`auto=<cutoff>`;;
Choose between `full` and `incremental` with a heuristic.
Currently `incremental` is used when there are at most
_<cutoff>_ incoming commits (1000 by default), and `full`
otherwise. The heuristic may change in future versions.
--
+
Unknown values are treated as `full`, with a warning.
transfer.credentialsInUrl::
A configured URL can contain plaintext credentials in the form
`<protocol>://<user>:<password>@<domain>/<path>`. You may want
to warn or forbid the use of such configuration (in favor of
using linkgit:git-credential[1]). This will be used on
linkgit:git-clone[1], linkgit:git-fetch[1], linkgit:git-push[1],
and any other direct use of the configured URL.
+
Note that this is currently limited to detecting credentials in
`remote.<name>.url` configuration; it won't detect credentials in
`remote.<name>.pushurl` configuration.
+
You might want to enable this to prevent inadvertent credentials
exposure, e.g. because:
+
* The OS or system where you're running git may not provide a way or
otherwise allow you to configure the permissions of the
configuration file where the username and/or password are stored.
* Even if it does, having such data stored "at rest" might expose you
in other ways, e.g. a backup process might copy the data to another
system.
* The git programs will pass the full URL to one another as arguments
on the command-line, meaning the credentials will be exposed to other
unprivileged users on systems that allow them to see the full
process list of other users. On linux the "hidepid" setting
documented in procfs(5) allows for configuring this behavior.
+
If such concerns don't apply to you then you probably don't need to be
concerned about credentials exposure due to storing sensitive
data in git's configuration files. If you do want to use this, set
`transfer.credentialsInUrl` to one of these values:
+
* `allow` (default): Git will proceed with its activity without warning.
* `warn`: Git will write a warning message to `stderr` when parsing a URL
with a plaintext credential.
* `die`: Git will write a failure message to `stderr` when parsing a URL
with a plaintext credential.
transfer.fsckObjects::
When `fetch.fsckObjects` or `receive.fsckObjects` are
not set, the value of this variable is used instead.
Defaults to false.
+
When set, the fetch or receive will abort in the case of a malformed
object or a link to a nonexistent object. In addition, various other
issues are checked for, including legacy issues (see `fsck.<msg-id>`),
and potential security issues like the existence of a `.GIT` directory
or a malicious `.gitmodules` file (see the release notes for v2.2.1
and v2.17.1 for details). Other sanity and security checks may be
added in future releases.
+
On the receiving side, failing fsckObjects will make those objects
unreachable, see "QUARANTINE ENVIRONMENT" in
linkgit:git-receive-pack[1]. On the fetch side, malformed objects will
instead be left unreferenced in the repository.
+
Due to the non-quarantine nature of the `fetch.fsckObjects`
implementation it cannot be relied upon to leave the object store
clean like `receive.fsckObjects` can.
+
As objects are unpacked they're written to the object store, so there
can be cases where malicious objects get introduced even though the
"fetch" failed, only to have a subsequent "fetch" succeed because only
new incoming objects are checked, not those that have already been
written to the object store. That difference in behavior should not be
relied upon. In the future, such objects may be quarantined for
"fetch" as well.
+
For now, the paranoid need to find some way to emulate the quarantine
environment if they'd like the same protection as "push". E.g. in the
case of an internal mirror do the mirroring in two steps, one to fetch
the untrusted objects, and then do a second "push" (which will use the
quarantine) to another internal repo, and have internal clients
consume this pushed-to repository, or embargo internal fetches and
only allow them once a full "fsck" has run (and no new fetches have
happened in the meantime).
transfer.hideRefs::
String(s) `receive-pack` and `upload-pack` use to decide which
refs to omit from their initial advertisements. Use more than
one definition to specify multiple prefix strings. A ref that is
under the hierarchies listed in the value of this variable is
excluded, and is hidden when responding to `git push` or `git
fetch`. See `receive.hideRefs` and `uploadpack.hideRefs` for
program-specific versions of this config.
+
You may also include a `!` in front of the ref name to negate the entry,
explicitly exposing it, even if an earlier entry marked it as hidden.
If you have multiple hideRefs values, later entries override earlier ones
(and entries in more-specific config files override less-specific ones).
+
If a namespace is in use, the namespace prefix is stripped from each
reference before it is matched against `transfer.hiderefs` patterns. In
order to match refs before stripping, add a `^` in front of the ref name. If
you combine `!` and `^`, `!` must be specified first.
+
For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
is omitted from the advertisements. If `uploadpack.allowRefInWant` is set,
`upload-pack` will treat `want-ref refs/heads/master` in a protocol v2
`fetch` command as if `refs/namespaces/foo/refs/heads/master` did not exist.
`receive-pack`, on the other hand, will still advertise the object id the
ref is pointing to without mentioning its name (a so-called ".have" line).
+
Even if you hide refs, a client may still be able to steal the target
objects via the techniques described in the "SECURITY" section of the
linkgit:gitnamespaces[7] man page; it's best to keep private data in a
separate repository.
transfer.unpackLimit::
When `fetch.unpackLimit` or `receive.unpackLimit` are
not set, the value of this variable is used instead.
The default value is 100.
transfer.advertiseSID::
Boolean. When true, client and server processes will advertise their
unique session IDs to their remote counterpart. Defaults to false.
transfer.bundleURI::
When `true`, local `git clone` commands will request bundle
information from the remote server (if advertised) and download
bundles before continuing the clone through the Git protocol.
Defaults to `false`.
transfer.advertiseObjectInfo::
When `true`, the `object-info` capability is advertised by
servers. Defaults to false.