Git, CI/CD & GitOpsXCVIII · Git Hosting FailureGitHostingFail
Local bare repository fallback — the last resort
What you'll learn
- Bootstrap a local bare repository with git init --bare as the last-resort fallback
- Push the canonical state into the local bare repo from a clone that has it
- Serve the bare repo over SSH or local filesystem for engineer pushes during a complete outage
- Recognise the limits of the local fallback: single-region, no web UI, no pull-request workflow
- Distinguish the local-bare-recovery pattern from the mirror pattern (read-only) and the self-hosted fallback (full forge)
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
The local bare repository is the last-resort fallback when the canonical remote and the mirror are both unreachable. It is not a forge replacement - there is no web UI, no pull-request workflow, no CI integration - but it is a place to land commits when every other endpoint is down. The bare repository is bootstrapped on a host the team controls, populated from a clone that has the canonical state, and served over SSH or the local filesystem so engineers can push to it.
# Bootstrap the local bare repo
git init --bare /srv/git/infra.git
# Push the canonical state from a clone that has it
cd ~/infra
git remote add local file:///srv/git/infra.git
git push --all local
git push --tags local
The bare repo is a plain Git directory. There is no daemon
required for local filesystem access; engineers push via
file:///srv/git/infra.git or via SSH if the repo is on a
remote host.
flowchart LR
A["canonical remote\nunreachable"] --> B["clone with canonical state"]
B --> C["git push --all local\ngit push --tags local"]
C --> D["bare repo on /srv/git/infra.git"]
D --> E["engineer pushes to bare repo\nvia file:// or SSH"]
D --> F["CI runs against bare repo\nvia file:// or SSH"]
G["canonical recovers"] --> H["push bare repo state back to canonical"]
When the local bare is the right primitive
The local bare is the right primitive in two scenarios. First, the canonical and the mirror are both unreachable - a multi-region outage has taken down the forge and the mirror region, and the local bare is the only place to push. Second, the team needs to land commits during a planned outage - a maintenance window has the canonical in read-only mode and the local bare is the staging ground.
In both cases, the bare repo is the staging area. The canonical is the long-term home; the bare repo is the intermediate landing site until the canonical recovers.
# Bootstrap a bare repo from scratch (no clone)
git init --bare /srv/git/infra.git
# Bootstrap with state from an existing clone
git clone --bare ~/infra /srv/git/infra.git
git clone --bare is the alternative to git init --bare when
a clone already exists; both produce a bare directory with the
objects, refs, and HEAD. --bare from a clone copies the local
state; git init --bare starts empty.
Serving the bare repo
The bare repo is reachable over three transports:
- Local filesystem (
file:///srv/git/infra.git). The simplest transport; works only when the engineer or CI runner is on the same host. - SSH (
user@host:/srv/git/infra.git). The standard transport for cross-host access; the engineer authenticates with an SSH key. - Smart HTTP (requires
git-http-backendor a tool like Gitea, covered in Part XCVIII-05). The bare repo itself does not serve HTTP; a webserver with CGI or a dedicated tool is required.
For the last-resort fallback, SSH is the right transport. The team’s SSH keys are already provisioned; the bare repo lives on a bastion host; engineers push over SSH from any host that can reach the bastion.
# Push to the bare repo over SSH
git remote add local user@bastion.internal:/srv/git/infra.git
git push --all local
git push --tags local
The remote name local is convention; the role is determined
by the URL pattern. A production script identifies the local
bare by URL hostname or path, not by name.
The limits of the local fallback
The local bare is the last resort precisely because it lacks everything a forge provides:
- No web UI. Engineers cannot browse the repository, open pull requests, or review diffs in a browser. The fallback is CLI-only.
- No pull-request workflow. The bare repo accepts pushes
but does not enforce reviews. Engineers push directly to
mainif they need to. - No CI integration. The bare repo has no webhook, no status checks, no merge queue. CI must be configured separately to poll or fetch from the bare repo.
- Single-region. The bare repo lives on one host. A regional outage of the host takes the bare repo with it.
- No audit trail beyond Git. The bare repo’s audit trail is the Git history itself; there is no PR-level record of who approved what.
These limits are why the local bare is the last resort, not the first. A team that relies on the local bare for normal operation is a team that has lost the production discipline of the pull-request workflow.
From local bare back to canonical
The recovery sequence when the canonical recovers:
- Engineers stop pushing to the bare repo. A status broadcast announces the canonical is back.
- The on-call engineer pushes the bare repo’s state to the
canonical.
git push --all canonicalandgit push --tags canonicalfrom a clone that has the bare repo’s state. - CI runs against the canonical again. The CDN flip (Part
XCVIII-03) is reversed; the canonical URL is back as
origin. - The bare repo is decommissioned. A status broadcast confirms the bare repo is no longer the canonical landing site.
The push-back step is the highest-risk moment. A bare repo
that has been pushed to directly to main may have commits
that conflict with the canonical’s main. The push-back has
to be a merge or a force-push, depending on the discipline
the team followed during the outage.
# Push-back from bare repo to canonical
cd ~/infra
git remote add bare file:///srv/git/infra.git
git fetch bare
git merge --no-ff bare/main
git push origin main
The --no-ff merge preserves the bare-repo commits as a
distinct merge commit; the canonical’s history shows the
recovery.
Production discipline
- The local bare is the last resort, not the first. The mirror (Part XCVIII-03) and the multi-remote failover (Part XCVIII-02) come first.
- Bootstrap from a clone with
git clone --bare, not fromgit init --barefollowed by a manual copy. The clone preserves the refs and the config. - Serve over SSH, not the local filesystem. SSH gives cross-host access; the local filesystem is single-host.
- Push the bare repo’s state back to the canonical as soon as the canonical recovers. The bare repo is the staging ground, not the canonical.
- Rehearse the bare-repo recovery quarterly. The drill catches the push-back step’s risks.
Cross-course references
- Git, CI/CD & GitOps — Part XCVIII-02 (Multi-Remote Failover) is the engineer-side counterpart this lesson’s bare repo complements.
- Git, CI/CD & GitOps — Part XCVIII-05 (Self-Hosted Git as Fallback) is the next step up from the local bare: a full forge with a web UI.
- Linux for Production Sysadmins — Part XXXVII (ServiceHardening) covers the SSH hardening this lesson’s bare repo serves through.
Quiz
Knowledge check · 4 questions
Q1. The canonical remote and the team's mirror are both unreachable. The team needs a place to land commits. What is the right primitive?
Q2. A local bare repository created with `git init --bare` provides a full forge replacement, including a web UI, pull-request workflow, and CI integration.
Q3. Explain why the local bare repository is described as 'the staging ground, not the canonical', and what the team must do when the canonical remote recovers.
Q4. Diagnose the recovery gap and recommend the push-back sequence.
A team has used a local bare repository on a bastion host as the last-resort fallback during a multi-region outage. Engineers pushed directly to `main` on the bare repo during the outage because there was no time for a pull-request workflow. The canonical recovers after eight hours. The bare repo's `main` has 14 commits ahead of the canonical's `main`. The team's audit trail must show who pushed what during the outage.
Passing score: 75%. Answers are checked in this browser.