Append-only backup for git branches and tags. everref runs inside a
repository you already work in and copies selected refs to one or more
backup remotes as an event log that only ever grows: nothing on a backup
is ever deleted, overwritten, or force-updated. When history is rewritten,
the old history stays; when a branch is deleted, its last state stays. From
the log, the refs active at any past moment can be reconstructed.
It is a single binary with one runtime dependency — the git you already
have. No daemon, no database, no server component, no sudo, no credentials
of its own: every action is a plain git command, configuration lives in git
config, and removing everref leaves the repository exactly as it was.
git everref add --remote backup # protect the current branch
git everref run # back it upA protected ref can also be a branch of a remote you fetch from
(origin/main): everref fetches it first and backs it up, so one clone can
bridge an upstream project — a GitHub repository, a team server — straight
into the append-only backup.
git push --mirror follows deletions and force-pushes, so a mirror is only
as safe as the source. Hosting-platform "protected branches" guard one
platform's copy under that platform's rules. everref instead makes the
backup immune by construction: its only write operations are create a new
ref and fast-forward an existing one, and git itself refuses everything
else — on every transport, with no server configuration.
Every run decides from the backup remote's live state, never a local cache, so several clones can safely back up the same project to the same remote; git's rejection of non-fast-forward pushes is the final safeguard.
For each protected ref, the backup remote holds an event log under an
everref/ namespace, plus a journal recording when each tip was observed:
refs/heads/everref/heads/main/created_1752566400 # a lineage; fast-forwards as main advances
refs/heads/everref/heads/main/created_1752739200 # history was rewritten: new lineage, old one frozen
refs/heads/everref/heads/main/deleted_1752912000 # branch deleted: tombstone at its last tip
refs/heads/everref/journal/heads/main/journal # timeline of every observed tip
A normal commit fast-forwards the active lineage. A rewrite starts a new lineage and freezes the old one. A deletion writes a tombstone. A source remote that cannot be reached is an error, never a deletion — an outage cannot masquerade as intent. Start with docs/getting-started.md; the documentation index maps the rest, and the full reasoning, invariants, and failure analysis live in docs/design.md.
Complete — released as v1.0.0. Every feature of the design document is implemented and covered by unit tests and an end-to-end integration suite that runs on Linux and macOS in CI. Development proceeded in milestones, each merged after a full adversarial review cycle:
| Milestone | Scope |
|---|---|
| Core engine | add, rm, list, run, status, log, reset; local and bridged branches; journals; concurrent-clone safety |
| Restore | restore, restore --at, multi-remote reconciliation — the log proves itself |
| Trigger reconciler | --trigger git hooks (including reference-transaction for bridged branches), --schedule systemd user timers |
| Tags & expire | Tag backup (tags command), expire, man pages, shell completions |
| Hardening | Test-suite rebuild and documentation restructuring |
Requires git ≥ 2.20 — the only runtime dependency (≥ 2.28 for the
reference-transaction trigger). The binary is named git-everref, which
is exactly what makes git everref … work: git runs any git-<name>
executable found on your PATH as git <name>.
Everything that goes through git — backup, bridge mode, restore, hook
triggers, expire — works wherever git does. Only schedules need an
OS scheduler, and today that means systemd:
| Capability | Linux | macOS | Windows |
|---|---|---|---|
| Backup, bridge mode, restore, expire | ✓ | ✓ | ✓ |
Hook triggers (post-commit, pre-push, reference-transaction) |
✓ | ✓ | ✓ |
--schedule timers |
✓ systemd user units | — | — |
Hooks are plain sh blocks; on Windows, git's own shell runs them. Where
--schedule is unavailable, hook triggers cover the event-driven cases and
any scheduler you already have (launchd, cron, Task Scheduler) can run
git everref -C <repo> run --all — a scheduled run needs no
everref-managed plumbing. Linux and macOS are the tested platforms:
every change runs the full unit and integration suites on both in CI.
Windows builds and runs but is untested and does not yet serialise
concurrent runs per repository.
Download from the
releases page; each
archive carries the binary and the man pages, and a checksums.txt sits
alongside for verification:
VERSION=1.0.0 # pick the release you want
curl -LO \
"https://github.com/daojyun/git-everref/releases/download/v${VERSION}/git-everref_${VERSION}_linux_amd64.tar.gz"
tar -xzf "git-everref_${VERSION}_linux_amd64.tar.gz"
mkdir -p ~/.local/bin ~/.local/share/man/man1
install -m 755 git-everref ~/.local/bin/git-everref
ln -sf git-everref ~/.local/bin/everref # optional short alias
install -m 644 docs/man/everref.1 docs/man/git-everref.1 ~/.local/share/man/man1/(The snippet sticks to flags BSD tools understand, so it works verbatim on
macOS; swap linux for darwin in the archive name there.)
The one command below drops the git-everref binary into ~/go/bin; put
that directory on your PATH and git everref works immediately. On
Windows this is the way to install — no prebuilt archives are published
for it:
go install github.com/daojyun/git-everref@latestmake install # binary, everref alias link, and man pages into ~/.localcd your-project
git remote add backup git@backup.example.com:acme/your-project.git
git everref add main --remote backup # protect a branch
git everref add origin/main --remote backup # bridge an upstream branch
git everref run --all --dry-run # preview
git everref run --all # back up
git everref status --all # compare against the backup
git everref log main # event historyeverref reuses your existing git remotes and credentials; the backup remote
is best a dedicated bare repository — including a plain local folder
(git init --bare ~/backups/your-project.git, then git remote add backup
with that path; walkthrough in
docs/getting-started.md). Nothing everref does ever removes a
remote ref — the one rule operators must keep: never hand-rewrite anything
under everref/ on a backup (troubleshooting).
All code, tests, and documentation in this repository were written by Claude (Anthropic's AI assistant) working under human direction — the code is 100% AI-generated, and humans have not reviewed every line.
What stands behind it instead:
- every feature commit passed an adversarial review by an independent AI reviewer (findings were reproduced against real repositories before being accepted, and each cycle ran until an explicit approval);
- the full test suite — unit tests for all pure logic plus an end-to-end integration suite of ~50 scenarios that verifies the append-only guarantee directly against real git repositories — must pass before any commit;
- provenance is recorded per commit (
Co-Authored-Bytrailers).
Treat everref like any dependency you have not audited yourself: read the code that matters to you before trusting it with production data, and report anything questionable. AI review and thorough tests reduce risk; they do not replace human judgment.
make build # build ./everref
make test # unit tests (pure logic: decision table, naming, parsing)
make integration # end-to-end tests against real git repositories
make lint-shell # shellcheck + shfmt over the integration suites
make staticcheck # optional deeper Go analysis
make ci # gofmt + vet + tidy check + shell lint + everything aboveThe integration runner explains its own footprint: test/integration/run.sh --help documents that everything happens inside one temporary directory,
with systemctl disabled and git's global config isolated.
The suites are written against GNU coreutils. On macOS, put Homebrew's
gnubin on PATH first (as the CI job does):
brew install coreutils
export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH"The layout follows the design's separation of concerns:
internal/refpath canonical ref paths, event names, reserved components
internal/gitx thin exec layer over the system git (the only I/O path)
internal/gitcfg declarative config in git config
internal/eventlog pure core: snapshot parsing, lineages, the decision table
internal/journal per-ref timeline commits
internal/backup the run engine
internal/cli cobra commands, git-style conventions
Exit codes are stable: 0 success, 1 at least one ref failed or was
skipped, 2 usage or configuration error.