Skip to main content

git-localhost-store

Protect your local git repositories from accidental deletion.

Problem

A stray rm -rf can destroy weeks of work if you haven't pushed to a remote. Local git repositories are fragile and ephemeral.

Solution

Every repository's objects live in a central store, indexed by working directory path. Delete the entire working directory and the commits are still there, recoverable by recreating the directory.

How It Works

When you git init or git clone (or git add in a fresh repo), hooks run git-localhost-store, which:

  1. Moves .git/ into a per-repo store under ~/.local/state/git-localhost-store/repos/<encoded-path>/.
  2. Replaces .git with a symbolic link to that store.

After the swap, .git is a symlink rather than a directory. Git follows it transparently. Naive readers (lazy.nvim, ad-hoc shell scripts, IDE plugins) that do open(repo + "/.git/HEAD") work unchanged, because the symlink resolves through the filesystem.

Path encoding

claude-code-slug names the store: every character that is not ASCII alphanumeric becomes exactly one -.

/home/you/projects/myrepo → -home-you-projects-myrepo

It is a dependency rather than a copy because the name has to survive the tool that wrote it: a store is named by this function, so a second implementation that disagrees anywhere doesn't fail, it strands a repository in a directory nobody looks in.

Installation

uv tool install git-localhost-store
git-localhost-store-install

The second command is the one that touches your system, and it is idempotent -- re-run it after upgrading, or after moving the venv. It creates the store root, writes the hook template, points init.templateDir at it, and aims one stable path (~/.local/share/git-localhost-store/bin/git-localhost-store) at the freshly installed relocator.

git allows exactly one init.templateDir. If yours is already set to something else, the installer says so and changes nothing; merge the hooks by hand.

Existing repositories keep their old hooks and are unaffected -- hooks are copied at init time, not read from the template afterwards. To convert one, run git-localhost-store in it.

Recovery

After rm -rf of a working directory:

mkdir ~/projects/myrepo && cd ~/projects/myrepo
git init
git-localhost-store   # adopts the surviving store, restores tracked files

Re-cloning instead: if the workdir had a remote, a plain git clone into the original path works directly -- the hook force-syncs remote-tracking refs and fast-forwards the local branch when it can. It refuses only when the store holds local commits that are not a fast-forward of the fresh clone. That refusal wants a human, not another rm -rf.

Commands

git-localhost-store [HOOK-NAME]

Convert the repository containing the current directory, or recover it if its store already exists. Idempotent, and a no-op when .git is already a symlink, or is a gitfile (worktree or submodule). Any other shape is an error: it asserts and exits non-zero rather than guess.

Hooks pass their own name as the argument; you don't.

git-localhost-store-install

See Installation.

Layout

~/.local/share/git-localhost-store/    # written by the installer
├── bin/git-localhost-store            # -> the installed console script
└── template-repo/hooks/               # git init template
    ├── shared                         # the hook body
    └── post-{index-change,commit,checkout}  # -> shared

~/.local/state/git-localhost-store/    # your repositories -- back this up
└── repos/<encoded-path>/              # one gitdir per workdir

Limitations

  • Protects commits and staged changes, not unstaged modifications.
  • Recovery requires recreating the directory at the exact original path.
  • Stores in the state directory can still be deleted by hand.
  • Not a substitute for a remote.
  • One worktree per store. git worktree add from the central gitdir still works; it is just not automated here.

Design Principles

  • Automatic -- works without user intervention.
  • Transparent to naive readers -- .git/HEAD resolves through the symlink as an ordinary file.
  • Deterministic -- the recovery path follows from the workdir path.
  • Explicit errors -- failures are visible. No || true.
  • Idempotent -- hooks and git-localhost-store are safe to re-run.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

git_localhost_store-0.1.0.tar.gz (57.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

git_localhost_store-0.1.0-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file git_localhost_store-0.1.0.tar.gz.

File metadata

  • Download URL: git_localhost_store-0.1.0.tar.gz
  • Upload date:
  • Size: 57.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for git_localhost_store-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0e84ce4ddc6b5695a9b1d316ea39a0c0cba36efef6b3bdddbf099240340aa7a0
MD5 d7545afdca4b0cd28d93829dd6cfe80b
BLAKE2b-256 c6d26f778249deb8a47cb2c6b1b2074717c8a33dc8dfd662961a5ec883c78746

See more details on using hashes here.

File details

Details for the file git_localhost_store-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: git_localhost_store-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for git_localhost_store-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 341e2b5654e688fb2bdf9477d3df0518605e294b1e66b56c3203af29c137d6ad
MD5 ea442b7e3712d596a75fe717c8e40a4f
BLAKE2b-256 2243ec8b51929b7576e4e449e0a2d49088538675a73e88497c7f1e2988c02945

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page