Help us shape the future of Go! Take the 2026 Go Developer Survey

emkin

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: MIT

README

Emkin

One content-addressed pin for an entire multi-repo tree.

Emkin snapshots the full state of a superrepo: every nested git submodule at any depth, plus the config files git does not govern. It hashes that state into a single id, detects drift against it, exports it as a portable tarball, and rolls any machine back to it.

Why

Large superrepos have no single identity for "the state that was running":

  • Commit hashes cover git only. Config and env files drift silently.
  • A deleted branch makes an old state unrecoverable after git gc.
  • Production machines diverge with no way to prove it.

Emkin gives that state one name, keeps it recoverable, and proves divergence.

How it works

Each repo in the tree becomes a Merkle node:

node hash = sha256(commit, dirty state, redacted paths,
                   sorted config-file hashes, sorted child-node hashes)

The root node hash identifies the whole state. The manifest is canonical JSON, so identical states on two machines produce identical pin ids. emkin show prints the tree as a level cake, one rollup hash per nesting level:

L0  233003491b73   1 repo
L1  b55834db8e6a  13 repos
L2  2be8a2afcfe0  37 repos
L3  c45c8fc78526   4 repos
L4  ea6ffdd673ac   1 repo

emkin diff and emkin verify compare top-down. Equal node hashes prune whole subtrees, so drift resolves to the exact repo, commit, or file in seconds, even across 56 repos.

Survives deleted branches

Every pin writes an anchor ref (refs/emkin/pins/<id>) in every repo and submodule, so pinned commits survive branch deletion and git gc --prune=now. emkin export additionally packs one git bundle per repo, so a pin restores on a fresh clone even after the remote branch is gone.

Secrets

Files matching secret patterns (.env*, *.pem, *credentials* by default) are stored age-encrypted, never plaintext. Dirty-diff capture redacts secret file hunks and records the redacted paths in the manifest. Export refuses any blob that would leak secret bytes.

Known limit: a secret that was ever committed lives in git history, and the export bundles carry history. Emkin warns per tracked secret file on export. The fix is a history rewrite plus rotation, which no snapshot tool can do for you.

Install

From a release:

tar xzf emkin_<version>_linux_amd64.tar.gz
install -m 755 emkin ~/.local/bin/emkin

From source (Go 1.22+):

go install github.com/kiriketsuki/emkin/cmd/emkin@latest

The binary is static (CGO_ENABLED=0). It needs git (2.38+) on the machine, and ssh/scp for fleet commands.

Quickstart

cd /path/to/superrepo
emkin init --gen-key        # emkin.yaml, .emkin/, age identity
emkin pin -m "baseline"     # pin the whole tree
emkin show <pin>            # level cake and per-node detail
emkin verify                # drift against the applied pin, exit 1 on drift
emkin export                # self-contained tarball
emkin rollback <pin>        # back to a recorded state, safety pin first

Machines, using your ~/.ssh/config aliases:

emkin machine register prod-1 --ssh prod-1 --role production
emkin machine setup prod-1            # scp the binary over
emkin deploy <pin> prod-1             # export, upload, remote apply
emkin fleet status                    # one table: machine, pin, drift

Commands

Command Purpose
init Create emkin.yaml and .emkin/ (--gen-key adds an age identity)
pin Pin the current tree (--require-clean refuses dirty trees)
list, show Browse pins, print the level cake
verify Recompute the tree, report drift, non-zero exit on any drift
diff Compare two pins, name the exact drifted repo, commit, or file
export, apply Portable tarball out, full restore in (works on fresh clones)
rollback Detached checkout of a recorded state, config restore, safety pin first
machine, deploy, fleet SSH machine registry, remote apply, fleet drift table

Most commands support --json for scripting.

Design notes

  • Rollback always takes a safety pin first, so rollback is undoable.
  • Pins succeed on dirty trees and record the dirt (diff blob per repo).
  • Git operations shell out to the git binary with plumbing commands only.
  • Validated end to end against a production superrepo: 56 repos across 5 nesting levels, pinned in ~6 s, verified in ~3 s.

See docs/design/ for the full design and docs/specs/ for the spec.

License

MIT

Directories

Path Synopsis
cmd
emkin command
Command emkin is the entry point for the emkin binary.
Command emkin is the entry point for the emkin binary.
internal
cli
Package cli holds the cobra command tree.
Package cli holds the cobra command tree.
config
Package config owns emkin.yaml, the committed half of the emkin state.
Package config owns emkin.yaml, the committed half of the emkin state.
drift
Package drift compares two finalized manifests and localizes the difference.
Package drift compares two finalized manifests and localizes the difference.
gitscan
Package gitscan discovers a nested submodule tree and reads the git state of every repo in it.
Package gitscan discovers a nested submodule tree and reads the git state of every repo in it.
gittest
Package gittest builds throwaway git fixtures for tests.
Package gittest builds throwaway git fixtures for tests.
manifest
Package manifest holds the emkin tree model, the canonical JSON serializer, the Merkle node hashing, the per-level rollups, and the pin id.
Package manifest holds the emkin tree model, the canonical JSON serializer, the Merkle node hashing, the per-level rollups, and the pin id.
pinner
Package pinner turns a live checkout into a finalized manifest.
Package pinner turns a live checkout into a finalized manifest.
restore
Package restore puts a recorded manifest back onto a checkout.
Package restore puts a recorded manifest back onto a checkout.
secret
Package secret classifies matched files as config or secret, and encrypts or decrypts secret blobs with age.
Package secret classifies matched files as config or secret, and encrypts or decrypts secret blobs with age.
sshexec
Package sshexec runs emkin on a remote machine over SSH.
Package sshexec runs emkin on a remote machine over SSH.
store
Package store owns everything emkin keeps on disk under <superrepo>/.emkin.
Package store owns everything emkin keeps on disk under <superrepo>/.emkin.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL