Repository navigation
gitai 0.4.1
A correctness and robustness release, recommended for everyone, above all for deployments in shadow or authoritative storage mode and for those where agents can push. It also brings the policy reload that landed after 0.4.0. See "Upgrade" for what changes for clients.
Reference name limit
Reference names and symbolic reference targets over 1024 bytes are refused.
RPCs answer InvalidArgument. A push refuses only that reference, unless the
push is atomic. Existing references over the limit can still be read and deleted.
- An object pool's names under
refs/remotes/origin/may be 15 bytes longer,
which is what its refspec adds to a source name. The allowance goes by the
repository's path, so a repository at a pool-shaped path has it too. - A repository holding such a reference fails with a permanent error, until the
reference is deleted, when forking, creating or updating a replica, creating or
fetching into an object pool, restoring a backup,FetchBundle,
CreateRepositoryFromBundleandRewriteHistory. - Importing such a repository into the storage core answers FailedPrecondition
before anything is registered or uploaded, and names the first few references.
A repository with an incomplete registration from an earlier failed import is
refused the same way: run the commands below on the node, with writers stopped,
and import again to resume. - One such reference on a remote fails the whole of a mirror's
FetchRemote. UserLandon a branch name over the limit reports this limit.
To find such references (the second command covers an unborn HEAD) and delete one:
git -C <repository> for-each-ref --format='%(refname) %(symref)' | LC_ALL=C awk 'length($1) > 1024 || length($2) > 1024'
git -C <repository> symbolic-ref -q HEAD | LC_ALL=C awk 'length($0) > 1024'
git -C <repository> update-ref --no-deref -d <reference>
Keep --no-deref: without it, deleting a symbolic reference deletes its target.
In an object pool the first command also lists the allowed names of 1025 to 1039
bytes under refs/remotes/origin/. The DeleteRefs RPC and a push that deletes
the reference work too, where the repository's writes are allowed. A symbolic
reference other than HEAD that points at nothing is not checked when a
repository is created from a copy.
Check your repositories before upgrading a storage-core deployment: a node
rebuilt from a database that already holds such a name still writes it through
git. Delete those references first.
Fixes
- A refused create could overwrite a branch in the database (shadow and
authoritative). When two pushes raced to create one branch, the loser was told
it was rejected while the database kept its commit. A push that creates an
existing branch is now refused. Until a fuller fix, the whole push is refused,
so other references of a non-atomic push don't land in that case. Other rejected
updates of a non-atomic push are not addressed in this release. - Writes stalled after a failed git transaction (authoritative). A repository's
write turn stayed held for up to 10 s when git failed a prepare, because git
reports neither commit nor abort then. Every writer behind it waited. The turn now
ends with the git process, on update-ref, in-process updates and atomic pushes over
SSH and smart HTTP. New metric
graft_storage_ref_admission_released_unreported_total. Smart HTTP's
PostReceivePacknow returns whenreceive-packexits, even if the client's
stream is still open. - Cancelled commands left git's reference lock behind. A cancelled context sent
SIGKILL, so git could not clean up, and the next writer failed with "reference is
already locked" until housekeeping removed the lock after an hour. Commands now get
SIGTERM, and SIGKILL to the process group after 10 s if it outlives that. A process
that traps SIGTERM and exits 0 now returns success after cancellation, so callers
must check their context. A lock left by an out-of-memory kill or a crash can still
block writers for up to an hour. - Concurrent proposal sweeps failed each other. One sweep now runs at a time per
branch, bounded at 5 s after a land. New metric
graft_land_proposal_sweep_timeouts_total. The file tickets of a land are released
before its sweep. - Writers could fail when housekeeping removed a loose object directory. Gitaly's
own writers now re-create it. Pushes of fewer than 100 objects can still fail, rarely,
inside git; a retry succeeds, and nothing is corrupted (LIMITATIONS).
New
- The policy reloads without a restart. SIGUSR1 reloads the standalone policy
from the configuration file. The swap is atomic; an invalid file keeps the old
policy. See CONFIGURATION. graft policy check FILEvalidates a policy and, with-repo, replays recent
changesets against it. Exit 0 when it denies nothing, 1 when it would deny updates,
2 when invalid.
Docs and CI
- README and BENCH now agree and state what was measured. Benchmarks were not
repeated for this release, so the effect of these fixes on throughput is not measured. - STORAGE.md records two measurements that ended in "don't build": sharing directory
fsyncs, and moving reftable compaction out of the write path. - LIMITATIONS was checked against the code, claim by claim.
- More tests no longer depend on the speed of the machine.
Upgrade
Check for over-limit references first (above). No configuration or data migration.