drift
中文文档 ·
GitHub ·
Roadmap
Version control for creators — a content-addressed, chunk-deduplicated version
control system designed for writers, illustrators, and designers. Unlike Git,
which treats every file as opaque bytes, drift recognizes image and video
formats, shows meaningful metadata in diffs, and stores only what actually
changed through content-defined chunking.
Status: Phase 1–3.5 complete (local core + branches + filetype engines +
remote sync). GUI desktop app is a planned phase; see
docs/roadmap.md.
Why drift?
| Pain point with Git |
drift answer |
| 200 MB file changes by a small part → store the whole file again |
FastCDC content-defined chunking stores only the changed blocks |
| Staging area / commits / merge — a programmer's mental model |
save captures all changes automatically; no staging, no merge |
| Diff shows raw bytes for binary files |
Pluggable filetype engines (text/image/video/binary): text gets unified diff, images/videos show format and dimension changes |
| No visual timeline |
CLI stage shows history in tables; GUI visual timeline is Phase 4 |
| Branches mean merge conflicts |
Branches are pure forks for experimentation; user merges manually |
Features
- Content-addressed storage — BLAKE3 hashes verify integrity and dedupe
automatically across snapshots and branches.
- CDC chunking — FastCDC for variable-size content-defined chunks, with a
fixed-size fallback for very large files (>100 MB). zstd compression on top.
- No staging area —
drift save captures the working tree as-is. Authors
think about their work, not about indexes.
- Branches without merge — create experimental branches, switch freely,
restore from anywhere. No merge conflicts, ever.
- Filetype engines — text (unified diff), image (format/dimension/size
comparison, supports PNG/JPEG/GIF/WebP/BMP/TIFF), video (format detection +
dimension parsing, supports MP4/MOV/AVI/MKV/WebM), binary (fallback). New
engines plug in via a registry.
- Automatic watches —
drift watch on periodically scans the workspace
and auto-saves when changes are detected (default interval 300s), with
auto-saves hidden from log by default.
- Remote sync — push/pull to remote storage via WebDAV or SMB, with
incremental transfer and branch-scoped sync.
- Single binary — one static Go binary for macOS / Windows / Linux. No
runtime, no daemons to install.
Install
go install github.com/Alei-001/drift/cmd/drift@latest
Or build from source (with version metadata injected via ldflags):
git clone https://github.com/Alei-001/drift.git
cd drift
go build -ldflags "-X github.com/Alei-001/drift/internal/version.Version=v0.1.0" -o drift ./cmd/drift
Requires Go 1.25+.
Upgrade
Once a GitHub release is published, self-upgrade to the latest version:
drift upgrade # download and replace the current binary
drift upgrade --check # only check for a newer release
Release assets follow the naming convention
drift_<version>_<os>_<arch>.{zip|tar.gz} with an optional
drift_<version>_checksums.txt (SHA-256) that is verified when present.
Quick start
# Initialize a project
cd my-novel
drift init
# Save a snapshot
drift save -m "Chapter 1 draft"
# See what changed since the last save
drift status
# Browse history (current branch chain)
drift log
# Try an experimental direction
drift branch create rewrite-ending
drift switch rewrite-ending
# ... edit files ...
drift save -m "Alt ending v1"
# Switch back; the rewrite is preserved on its own branch
drift switch main
# Inspect a specific snapshot's file changes
drift log --detail id:12ab
# Restore the workspace to a previous snapshot (auto-backs up first)
drift restore id:12ab
# Undo the last save
drift undo
# Configure a remote and sync
drift remote add origin --url https://example.com/dav/my-novel --user <user>
drift push origin # push local data to remote
drift pull origin # pull latest data from remote
drift clone https://example.com/dav/my-novel my-novel # clone a remote repo
Commands
| Command |
Purpose |
drift init |
Create .drift/ repository |
drift save [-m <msg>] [--tag <name>] |
Save a snapshot of all changes |
drift status |
Show added / modified / deleted files |
drift log [--branch <name>] [--all] [--limit <n>] |
Browse snapshot history |
drift show <version> [<file>] |
List files in a snapshot, or display a file's content |
drift diff <v1> <v2> |
Diff two snapshots (file list or unified diff) |
drift restore <version> |
Restore the workspace to a snapshot (backs up first) |
drift undo |
Undo the last save |
drift branch {list,create,delete,rename} |
Manage branches |
drift switch <branch> |
Switch to a branch (optionally create with -c) |
drift tag {list,add,delete,rename} |
Manage tags |
drift watch {on,off,status,pause,resume} |
Background auto-save daemon |
drift ignore <pattern> |
Add ignore rules to .driftignore |
drift resolve <version> |
Resolve a version reference to a snapshot ID |
drift remote {add,list,remove,rename,set-url,show,test} |
Manage remote repository configuration |
drift push <remote> [--branch <name>] [--dry-run] |
Push local data to remote |
drift pull <remote> [--branch <name>] [--dry-run] |
Pull data from remote to local |
drift clone <remote-url> <path> |
Clone a remote repository to local |
drift ls-remote <remote> |
List branches and tags on a remote |
drift check |
Verify .drift/ storage integrity |
drift gc [--dry-run] |
Remove unreachable snapshots and chunks |
drift config {get,set,list} |
View and modify configuration |
drift version |
Show version, commit, and build info |
drift upgrade [--check] [--force] |
Self-upgrade to the latest GitHub release |
Version references
Commands that take a <version> accept:
head — current HEAD snapshot
id:<hash-prefix> — match by hash prefix (≥ 4 chars)
tag:<name> — resolve via tag
branch:<name> — resolve via branch head
<bare-name> — shorthand for branch:<bare-name>
Project layout
cmd/ CLI entry points (cobra commands) — no business logic
drift/ main binary
internal/ business implementation (not importable externally)
porcelain/ business logic: snapshot, branch, restore, lock, watch, gc
filetype/ pluggable type engines (text/image/video/binary)
chunker/ FastCDC + fixed-size chunking
storage/ Storer interface + shared helpers
backends/ filesystem (prod) and memory (tests) implementations
refname/ branch / tag name validation
stream/ chunk streaming helpers
remote/ remote sync: WebDAV/SMB protocols, push/pull transfer
core/ domain types: Hash, Chunk, Snapshot, FileEntry, Config, ...
util/ fsutil, glob, pathutil, format, cache
version/ build-time version metadata + self-upgrade
docs/ design and reference docs
See AGENTS.md for the full layering rules and conventions.
Documentation
Building and testing
go build ./... # build all packages
go test ./... # run all tests
go test -run TestFoo ./internal/porcelain/ # single test
No Makefile, no lint config — pure go toolchain. CI via GitHub Actions
(see .github/workflows/).
Protobuf codegen
Generated files live in internal/core/*.pb.go. Regenerate with:
protoc --proto_path=internal/core --go_out=internal/core --go_opt=paths=source_relative internal/core/snapshot.proto
protoc --proto_path=internal/core --go_out=internal/core --go_opt=paths=source_relative internal/core/index.proto
The --go_opt=paths=source_relative flag is required (see AGENTS.md).
Key dependencies
License
MIT — see the LICENSE file for details.