Compare commits
3 commits
a70f7eb2cb
...
86a49961ad
| Author | SHA1 | Date | |
|---|---|---|---|
| 86a49961ad | |||
| 0bc174e341 | |||
| d8710a79c9 |
7 changed files with 638 additions and 0 deletions
55
LICENSE.md
Normal file
55
LICENSE.md
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Blue Oak Model License
|
||||||
|
|
||||||
|
Version 1.0.0
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This license gives everyone as much permission to work with
|
||||||
|
this software as possible, while protecting contributors
|
||||||
|
from liability.
|
||||||
|
|
||||||
|
## Acceptance
|
||||||
|
|
||||||
|
In order to receive this license, you must agree to its
|
||||||
|
rules. The rules of this license are both obligations
|
||||||
|
under that agreement and conditions to your license.
|
||||||
|
You must not do anything with this software that triggers
|
||||||
|
a rule that you cannot or will not follow.
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
Each contributor licenses you to do everything with this
|
||||||
|
software that would otherwise infringe that contributor's
|
||||||
|
copyright in it.
|
||||||
|
|
||||||
|
## Notices
|
||||||
|
|
||||||
|
You must ensure that everyone who gets a copy of
|
||||||
|
any part of this software from you, with or without
|
||||||
|
changes, also gets the text of this license or a link to
|
||||||
|
<https://blueoakcouncil.org/license/1.0.0>.
|
||||||
|
|
||||||
|
## Excuse
|
||||||
|
|
||||||
|
If anyone notifies you in writing that you have not
|
||||||
|
complied with [Notices](#notices), you can keep your
|
||||||
|
license by taking all practical steps to comply within 30
|
||||||
|
days after the notice. If you do not do so, your license
|
||||||
|
ends immediately.
|
||||||
|
|
||||||
|
## Patent
|
||||||
|
|
||||||
|
Each contributor licenses you to do everything with this
|
||||||
|
software that would otherwise infringe any patent claims
|
||||||
|
they can license or become able to license.
|
||||||
|
|
||||||
|
## Reliability
|
||||||
|
|
||||||
|
No contributor can revoke this license.
|
||||||
|
|
||||||
|
## No Liability
|
||||||
|
|
||||||
|
***As far as the law allows, this software comes as is,
|
||||||
|
without any warranty or condition, and no contributor
|
||||||
|
will be liable to anyone for any damages related to this
|
||||||
|
software or this license, under any kind of legal claim.***
|
||||||
84
README.md
Normal file
84
README.md
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
# arc ![license] ![activity]
|
||||||
|
|
||||||
|
[license]: https://badge.hanna.lol/license/BlueOak-1.0.0
|
||||||
|
[activity]: https://badge.hanna.lol/activity/hanna/arc
|
||||||
|
|
||||||
|
A delta-based version control system written in Rust.
|
||||||
|
|
||||||
|
Unlike Git's snapshot-based model, Arc stores incremental deltas using
|
||||||
|
ZSTD-compressed MessagePack files. Changes are automatically tracked
|
||||||
|
without manual staging, and commits are immutable once created.
|
||||||
|
|
||||||
|
Arc uses a **bookmark** system instead of branches, and bridges to Git
|
||||||
|
remotes for push, pull, clone, and sync operations via `libgit2`.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Incremental delta storage (ZSTD + MessagePack)
|
||||||
|
- Automatic change tracking (no staging step)
|
||||||
|
- Bookmarks and immutable tags
|
||||||
|
- Named stashes
|
||||||
|
- Three-way merge and graft (cherrypick/rebase)
|
||||||
|
- Git bridge for remote operations (push, pull, clone, migrate, sync)
|
||||||
|
- Optional SSH commit signing
|
||||||
|
- Per-repo and global YAML configuration with aliases
|
||||||
|
- `.arcignore` / `.ignore` support
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Arc builds exclusively through Nix:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix build
|
||||||
|
```
|
||||||
|
|
||||||
|
The flake uses `nixpkgs-unstable`, `flake-parts`, `fenix`, and `crane`.
|
||||||
|
|
||||||
|
A dev shell is available for iterative work:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix develop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
arc init [path] Initialize a new repository
|
||||||
|
arc commit <message> Commit current changes
|
||||||
|
arc status Show changes since last commit
|
||||||
|
arc diff [start..end] Show a diff of changes
|
||||||
|
arc log [start..end] Show commit history
|
||||||
|
arc show <mark|tag|commit> Show details of a ref or commit
|
||||||
|
arc history <file> [start..end] Show per-line modification history
|
||||||
|
|
||||||
|
arc switch <mark|tag> Switch worktree to a bookmark or tag
|
||||||
|
arc merge <mark|tag> Merge a bookmark or tag into the worktree
|
||||||
|
arc revert <commit|start..end> Revert a commit or range
|
||||||
|
arc reset [file...] Reset worktree to the last commit
|
||||||
|
arc graft <target> --onto <dest> Cherrypick commits onto a bookmark
|
||||||
|
|
||||||
|
arc mark add|rm|list|rename Manage bookmarks
|
||||||
|
arc tag add|rm|list Manage tags
|
||||||
|
arc stash create|use|push|pop|rm|list Manage named stashes
|
||||||
|
|
||||||
|
arc push [-r remote] Push to a git remote
|
||||||
|
arc pull [-r remote] Pull from a git remote
|
||||||
|
arc clone [-b branch] <url> [path] Clone a git remote as an arc repo
|
||||||
|
arc migrate Convert a git repo to an arc repo
|
||||||
|
arc sync [-p] Sync bookmarks and tags with remote
|
||||||
|
|
||||||
|
arc remote add|rm|list Manage remotes
|
||||||
|
arc config set|get|show|unset [-g] Manage configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix develop -c cargo test
|
||||||
|
nix develop -c cargo clippy
|
||||||
|
nix develop -c cargo fmt --check
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[Blue Oak Model License 1.0.0](LICENSE.md)
|
||||||
120
docs/architecture.md
Normal file
120
docs/architecture.md
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
# Architecture
|
||||||
|
|
||||||
|
Arc is a version control system with its own data model, storage format, and a
|
||||||
|
git bridge for interoperability.
|
||||||
|
|
||||||
|
## Repository Layout
|
||||||
|
|
||||||
|
An arc repository keeps all state in an `.arc/` directory at the worktree root:
|
||||||
|
|
||||||
|
| Path | Format | Purpose |
|
||||||
|
|------|--------|---------|
|
||||||
|
| `HEAD` | YAML | Current state — one of three variants: **unborn** (no commits yet; has `bookmark`), **attached** (on a bookmark; has `bookmark` + `commit`), or **detached** (raw commit; has `commit`). |
|
||||||
|
| `config.yml` | YAML | Local repository configuration. |
|
||||||
|
| `commits/<id>.zst` | Zstandard-compressed MessagePack | Commit objects. Each file contains a `CommitObject` that bundles a `Commit` and its `Delta`. |
|
||||||
|
| `bookmarks/<name>.yml` | YAML | One file per bookmark. Contains a `RefTarget` with an optional `commit` field. |
|
||||||
|
| `tags/<name>.yml` | YAML | Same format as bookmarks. |
|
||||||
|
| `stashes/state.yml` | YAML | Tracks the active stash. |
|
||||||
|
| `stashes/named/<name>.yml` | YAML | Per-stash state files. |
|
||||||
|
| `remotes.yml` | YAML | Map of remote names to URLs. |
|
||||||
|
| `git/` | Bare git repo | Shadow repository used by the git bridge. |
|
||||||
|
| `git-map.yml` | YAML | Bidirectional mapping between arc commit IDs and git OIDs. |
|
||||||
|
|
||||||
|
## Data Model (`src/model.rs`)
|
||||||
|
|
||||||
|
`CommitId` and `DeltaId` are newtype wrappers around `String`, holding SHA-256
|
||||||
|
hex hashes.
|
||||||
|
|
||||||
|
**Commit** — `id`, `parents` (Vec), `delta` (DeltaId), `message`,
|
||||||
|
`author` (optional `Signature`), `timestamp` (i64 unix),
|
||||||
|
`ssh_signature` (optional PEM string).
|
||||||
|
|
||||||
|
**Delta** — `id`, `base` (optional parent CommitId), `changes` (Vec of
|
||||||
|
`FileChange`).
|
||||||
|
|
||||||
|
**FileChange** — `path` plus a `kind`: Add, Modify, Delete, or Rename.
|
||||||
|
|
||||||
|
**FileContentDelta** — either `Full { bytes }` (complete snapshot) or
|
||||||
|
`Patch { format, data }` (incremental).
|
||||||
|
|
||||||
|
**Head** — enum with variants Unborn, Attached, and Detached.
|
||||||
|
|
||||||
|
## Storage (`src/store.rs`)
|
||||||
|
|
||||||
|
`CommitObject` bundles a `Commit` and its `Delta` into a single unit that is
|
||||||
|
serialized as MessagePack, then compressed with Zstandard at level 3. Files are
|
||||||
|
written atomically (write to `.tmp`, then rename). IDs are computed by SHA-256
|
||||||
|
hashing the MessagePack-serialized content-addressable data.
|
||||||
|
|
||||||
|
## Tracking (`src/tracking.rs`)
|
||||||
|
|
||||||
|
`FileTree` is a `BTreeMap<String, Vec<u8>>` mapping relative paths to file
|
||||||
|
content.
|
||||||
|
|
||||||
|
- `scan_worktree` — recursively walks the working directory, respecting ignore
|
||||||
|
rules and skipping `.arc/` and `.git/`.
|
||||||
|
- `materialize_committed_tree` — rebuilds the full file tree by replaying the
|
||||||
|
linear delta chain from the root commit.
|
||||||
|
- `detect_changes` — compares the committed tree against the worktree to produce
|
||||||
|
a list of `FileChange` entries (adds, modifies, deletes).
|
||||||
|
|
||||||
|
## Ignore System (`src/ignore.rs`)
|
||||||
|
|
||||||
|
Reads `.arcignore` first, falling back to `.ignore`. Always ignores `.arc/` and
|
||||||
|
`.git/`.
|
||||||
|
|
||||||
|
- `*` and `?` glob wildcards.
|
||||||
|
- `!` prefix for negation.
|
||||||
|
- Patterns without `/` match any path component; patterns with `/` match the
|
||||||
|
full relative path.
|
||||||
|
- Patterns ending with `/` match directories only.
|
||||||
|
|
||||||
|
## Git Bridge (`src/bridge.rs`)
|
||||||
|
|
||||||
|
Maintains a shadow bare git repository under `.arc/git/`.
|
||||||
|
|
||||||
|
`GitMap` provides bidirectional mapping (`arc_to_git` / `git_to_arc`) persisted
|
||||||
|
in `.arc/git-map.yml`.
|
||||||
|
|
||||||
|
- `arc_to_git` recursively converts arc commits to git commits, materializing
|
||||||
|
file trees as git tree objects.
|
||||||
|
- `git_to_arc` does the reverse, computing deltas from git tree diffs.
|
||||||
|
- SSH authentication via agent or key files (`~/.ssh/id_ed25519`, `id_rsa`,
|
||||||
|
`id_ecdsa`).
|
||||||
|
|
||||||
|
## Merge (`src/merge.rs`)
|
||||||
|
|
||||||
|
Full three-way merge with line-level merging for text files using Myers diff.
|
||||||
|
Conflicts are marked with `<<<<<<< ours` / `=======` / `>>>>>>> theirs`.
|
||||||
|
Binary files fall back to keeping the "ours" version on conflict.
|
||||||
|
|
||||||
|
## Signing (`src/signing.rs`)
|
||||||
|
|
||||||
|
Optional SSH key signing using the `ssh-key` crate. Signs with SHA-512 under
|
||||||
|
the `arc` namespace. Verification extracts the public key from the signature
|
||||||
|
itself. Supports `~` expansion in key paths.
|
||||||
|
|
||||||
|
## Source Modules
|
||||||
|
|
||||||
|
| Module | Responsibility |
|
||||||
|
|--------|----------------|
|
||||||
|
| `main.rs` | Entry point, macro definitions |
|
||||||
|
| `cli.rs` | Clap-based CLI parsing and command dispatch |
|
||||||
|
| `model.rs` | Core data types |
|
||||||
|
| `store.rs` | Commit/delta serialization and content-addressing |
|
||||||
|
| `tracking.rs` | Worktree scanning, change detection, commit logic |
|
||||||
|
| `repo.rs` | Repository init/open/discover, path validation |
|
||||||
|
| `config.rs` | YAML config loading, merging (local-first), effective config |
|
||||||
|
| `refs.rs` | Bookmark/tag CRUD, switch, worktree write/clean |
|
||||||
|
| `bridge.rs` | Git bridge (shadow repo, push, pull, clone, migrate, sync) |
|
||||||
|
| `diff.rs` | Unified diff rendering |
|
||||||
|
| `inspect.rs` | Log, show, history (blame), Myers diff |
|
||||||
|
| `merge.rs` | Three-way merge |
|
||||||
|
| `modify.rs` | Reset, revert, merge command, graft |
|
||||||
|
| `resolve.rs` | Target/range resolution (bookmarks, tags, prefixes, HEAD) |
|
||||||
|
| `ignore.rs` | Ignore file parsing and matching |
|
||||||
|
| `signing.rs` | SSH commit signing and verification |
|
||||||
|
| `stash.rs` | Named stash system |
|
||||||
|
| `remote.rs` | Remote management (remotes.yml) |
|
||||||
|
| `error.rs` | Error types |
|
||||||
|
| `ui.rs` | Colored output formatting |
|
||||||
180
docs/commands.md
Normal file
180
docs/commands.md
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
# Command Reference
|
||||||
|
|
||||||
|
## Global Flags
|
||||||
|
|
||||||
|
- `-v` / `--verbose` — Increase verbosity (up to `-vvv`).
|
||||||
|
- `--version` — Show version.
|
||||||
|
- `--help` / `help` — Show help.
|
||||||
|
|
||||||
|
## Core
|
||||||
|
|
||||||
|
### `arc init [path]`
|
||||||
|
|
||||||
|
Initialize a new arc repository. Creates the `.arc/` directory structure including `commits/`, `bookmarks/`, `tags/`, `stashes/`, `config.yml`, and `HEAD`. The default bookmark is `main`.
|
||||||
|
|
||||||
|
### `arc commit <message>`
|
||||||
|
|
||||||
|
Commit all current changes. No staging area is needed — changes are detected automatically by comparing the worktree to the last commit. Creates a ZSTD-compressed MessagePack commit object in `.arc/commits/`. If a signing key is configured (`user.key`), the commit is signed with SSH.
|
||||||
|
|
||||||
|
### `arc status`
|
||||||
|
|
||||||
|
Show added, modified, and deleted files since the last commit.
|
||||||
|
|
||||||
|
### `arc diff [start..end]`
|
||||||
|
|
||||||
|
Show a unified diff of changes. Without arguments, shows uncommitted changes. With a range, shows the diff between two commits.
|
||||||
|
|
||||||
|
### `arc log [start..end]`
|
||||||
|
|
||||||
|
Show commit history. Without arguments, shows all commits. Supports ranges like `start..end` (inclusive, either side optional). Each entry shows commit ID, timestamp, author, message, and a `[signed]` tag if applicable.
|
||||||
|
|
||||||
|
### `arc show <mark|tag|commit>`
|
||||||
|
|
||||||
|
Show full details of a commit including author, date, parent(s), signature verification status, and the diff it introduced. Resolves bookmarks, tags, commit IDs, and commit prefixes.
|
||||||
|
|
||||||
|
### `arc history <file> [start..end]`
|
||||||
|
|
||||||
|
Show per-line blame/annotation for a file, showing which commit last modified each line. Uses the Myers diff algorithm.
|
||||||
|
|
||||||
|
## Branching (Bookmarks)
|
||||||
|
|
||||||
|
### `arc mark add <name> [commit]`
|
||||||
|
|
||||||
|
Create a bookmark at the given commit. Defaults to HEAD if no commit is specified.
|
||||||
|
|
||||||
|
### `arc mark rm <name>`
|
||||||
|
|
||||||
|
Remove a bookmark. Cannot remove the active bookmark.
|
||||||
|
|
||||||
|
### `arc mark list`
|
||||||
|
|
||||||
|
List all bookmarks, marking the active one.
|
||||||
|
|
||||||
|
### `arc mark rename <name> <new>`
|
||||||
|
|
||||||
|
Rename a bookmark. Updates HEAD if the active bookmark is renamed.
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
### `arc tag add <name> [commit]`
|
||||||
|
|
||||||
|
Create an immutable tag at the given commit. Defaults to HEAD if no commit is specified. Tags cannot be overwritten.
|
||||||
|
|
||||||
|
### `arc tag rm <name>`
|
||||||
|
|
||||||
|
Remove a tag.
|
||||||
|
|
||||||
|
### `arc tag list`
|
||||||
|
|
||||||
|
List all tags with their commit IDs.
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
### `arc switch <mark|tag>`
|
||||||
|
|
||||||
|
Switch the worktree to a bookmark or tag. Switching to a bookmark attaches HEAD. Switching to a tag or raw commit detaches HEAD. Requires a clean worktree.
|
||||||
|
|
||||||
|
### `arc merge <mark|tag>`
|
||||||
|
|
||||||
|
Three-way merge from a bookmark or tag into the current worktree. Creates a merge commit with two parents. Reports conflicts with `<<<<<<< ours / ======= / >>>>>>> theirs` markers.
|
||||||
|
|
||||||
|
## Undo & Modification
|
||||||
|
|
||||||
|
### `arc revert <commit|start..end>`
|
||||||
|
|
||||||
|
Create a new commit that reverses the changes from a commit or range. Uses three-way merge.
|
||||||
|
|
||||||
|
### `arc reset [file...]`
|
||||||
|
|
||||||
|
Reset the worktree to match the last commit. Without arguments, resets all files. With file arguments, resets only those files.
|
||||||
|
|
||||||
|
### `arc graft <target> --onto <bookmark|commit>`
|
||||||
|
|
||||||
|
Cherry-pick/rebase commit(s) onto a target. Uses three-way merge. If the target is a bookmark, updates the bookmark pointer.
|
||||||
|
|
||||||
|
## Stash
|
||||||
|
|
||||||
|
### `arc stash create <name>`
|
||||||
|
|
||||||
|
Create a named stash and set it as active.
|
||||||
|
|
||||||
|
### `arc stash use <name>`
|
||||||
|
|
||||||
|
Switch the active stash.
|
||||||
|
|
||||||
|
### `arc stash push`
|
||||||
|
|
||||||
|
Push dirty changes onto the active stash and reset the worktree.
|
||||||
|
|
||||||
|
### `arc stash pop`
|
||||||
|
|
||||||
|
Pop the most recent entry from the active stash and apply it to the worktree. Requires a clean worktree and matching HEAD.
|
||||||
|
|
||||||
|
### `arc stash rm <name>`
|
||||||
|
|
||||||
|
Remove a named stash.
|
||||||
|
|
||||||
|
### `arc stash list`
|
||||||
|
|
||||||
|
List all named stashes with entry counts.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### `arc config set [-g] <key> <value>`
|
||||||
|
|
||||||
|
Set a config value. Use `-g` for global config. Keys use `section.field` format (e.g. `user.name`, `default.bookmark`, `aliases.c`).
|
||||||
|
|
||||||
|
### `arc config get [-g] <key>`
|
||||||
|
|
||||||
|
Get a config value. Without `-g`, resolves local first, then falls back to global.
|
||||||
|
|
||||||
|
### `arc config show [-g]`
|
||||||
|
|
||||||
|
Show full configuration as YAML. Without `-g`, shows effective (merged) config.
|
||||||
|
|
||||||
|
### `arc config unset [-g] <key>`
|
||||||
|
|
||||||
|
Remove a config key.
|
||||||
|
|
||||||
|
### Valid Config Fields
|
||||||
|
|
||||||
|
- `user.name` — Author name.
|
||||||
|
- `user.email` — Author email.
|
||||||
|
- `user.key` — SSH key path for commit signing.
|
||||||
|
- `default.bookmark` — Default bookmark name (default: `main`).
|
||||||
|
- `default.remote` — Default remote name (default: `origin`).
|
||||||
|
- `aliases.<name>` — Command aliases, expanded at the CLI level.
|
||||||
|
|
||||||
|
## Git Bridge & Remotes
|
||||||
|
|
||||||
|
### `arc remote add <name> <url>`
|
||||||
|
|
||||||
|
Add a remote. Stored in `.arc/remotes.yml`.
|
||||||
|
|
||||||
|
### `arc remote rm <name>`
|
||||||
|
|
||||||
|
Remove a remote.
|
||||||
|
|
||||||
|
### `arc remote list`
|
||||||
|
|
||||||
|
List all configured remotes.
|
||||||
|
|
||||||
|
### `arc push [-r remote]`
|
||||||
|
|
||||||
|
Push to a git remote. Converts arc commits to git commits via a shadow git repo (`.arc/git/`), with the mapping stored in `.arc/git-map.yml`.
|
||||||
|
|
||||||
|
### `arc pull [-r remote]`
|
||||||
|
|
||||||
|
Pull from a git remote. Converts git commits to arc commits. Fast-forward only.
|
||||||
|
|
||||||
|
### `arc clone [-b branch] <url> [path]`
|
||||||
|
|
||||||
|
Clone a git remote and convert it to an arc repository.
|
||||||
|
|
||||||
|
### `arc migrate`
|
||||||
|
|
||||||
|
Convert an existing git repository to an arc repository. Imports all branches as bookmarks and all tags. Preserves commit history.
|
||||||
|
|
||||||
|
### `arc sync [-p]`
|
||||||
|
|
||||||
|
Sync all bookmarks and tags to the shadow git repo. With `-p`, also pushes to the default remote.
|
||||||
64
docs/configuration.md
Normal file
64
docs/configuration.md
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
Arc uses YAML configuration files.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
user:
|
||||||
|
name: hanna
|
||||||
|
email: me@hanna.lol
|
||||||
|
key: ~/.ssh/id_ed25519
|
||||||
|
|
||||||
|
default:
|
||||||
|
bookmark: main
|
||||||
|
remote: origin
|
||||||
|
|
||||||
|
aliases:
|
||||||
|
c: commit
|
||||||
|
p: push
|
||||||
|
l: pull
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Locations
|
||||||
|
|
||||||
|
- **Local config**: `.arc/config.yml` inside the repository. Created automatically on `arc init` with default bookmark/remote values.
|
||||||
|
- **Global config**: `$XDG_CONFIG_HOME/arc/config.yml`, or `~/.config/arc/config.yml` if `XDG_CONFIG_HOME` is not set.
|
||||||
|
|
||||||
|
## Resolution Order
|
||||||
|
|
||||||
|
Local config values take priority over global config values. For each field, the local value is checked first; if not set, the global value is used. Aliases from both configs are merged, with local aliases overriding global ones with the same name.
|
||||||
|
|
||||||
|
## Sections
|
||||||
|
|
||||||
|
### `user`
|
||||||
|
|
||||||
|
| Key | Description |
|
||||||
|
|---|---|
|
||||||
|
| `user.name` | Author name for commits. |
|
||||||
|
| `user.email` | Author email for commits. Both name and email must be set for author info to appear on commits. |
|
||||||
|
| `user.key` | Path to an SSH private key for commit signing (e.g. `~/.ssh/id_ed25519`). Tilde expansion (`~`) is supported. When set, commits are automatically signed. |
|
||||||
|
|
||||||
|
### `default`
|
||||||
|
|
||||||
|
| Key | Description |
|
||||||
|
|---|---|
|
||||||
|
| `default.bookmark` | Default bookmark name (used on init). Defaults to `main`. |
|
||||||
|
| `default.remote` | Default remote name (used by push/pull/sync). Defaults to `origin`. |
|
||||||
|
|
||||||
|
### `aliases`
|
||||||
|
|
||||||
|
Maps short names to command names. For example, `aliases.c: commit` lets you run `arc c "message"` instead of `arc commit "message"`. Aliases are expanded at the CLI level before command dispatch. Any alias key is valid; the value should be a valid arc command name.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```
|
||||||
|
arc config set <key> <value> Set a local config value.
|
||||||
|
arc config set -g <key> <value> Set a global config value.
|
||||||
|
arc config get <key> Get a value (local first, then global).
|
||||||
|
arc config get -g <key> Get a value from global config only.
|
||||||
|
arc config show Show the effective (merged) configuration.
|
||||||
|
arc config show -g Show only the global configuration.
|
||||||
|
arc config unset <key> Remove a key from local config.
|
||||||
|
arc config unset -g <key> Remove a key from global config.
|
||||||
|
```
|
||||||
|
|
||||||
|
Keys use dot notation: `section.field` (e.g. `user.name`, `default.remote`, `aliases.st`).
|
||||||
70
docs/getting-started.md
Normal file
70
docs/getting-started.md
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Getting Started
|
||||||
|
|
||||||
|
Arc is a delta-based version control system written in Rust. It builds exclusively through Nix.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Arc uses a Nix flake (nixpkgs-unstable, flake-parts, fenix, crane):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix build
|
||||||
|
```
|
||||||
|
|
||||||
|
Enter a dev shell with `nix develop` (provides rustc, cargo, clippy, rustfmt, git, pkg-config, cmake, perl).
|
||||||
|
|
||||||
|
Run Arc with `nix run` or `result/bin/arc` after building.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
```sh
|
||||||
|
arc config set user.name "yourname"
|
||||||
|
arc config set user.email "you@example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
Global config lives at `$XDG_CONFIG_HOME/arc/config.yml` (or `~/.config/arc/config.yml`).
|
||||||
|
|
||||||
|
## Creating a Repository
|
||||||
|
|
||||||
|
```sh
|
||||||
|
arc init [path]
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a `.arc/` directory containing:
|
||||||
|
|
||||||
|
- `commits/` — commit storage
|
||||||
|
- `bookmarks/` — branches (default: `main`)
|
||||||
|
- `tags/` — tagged commits
|
||||||
|
- `stashes/` — stashed changes
|
||||||
|
- `config.yml` — repository config
|
||||||
|
- `HEAD` — current position
|
||||||
|
|
||||||
|
The default remote is `origin`.
|
||||||
|
|
||||||
|
## Tracking Changes
|
||||||
|
|
||||||
|
Arc tracks changes automatically — there is no staging area.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
arc status # see what changed
|
||||||
|
arc commit <message> # commit all changes
|
||||||
|
arc log # view history
|
||||||
|
arc diff # see diffs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ignoring Files
|
||||||
|
|
||||||
|
Create a `.arcignore` or `.ignore` file with gitignore-like glob syntax. Prefix a pattern with `!` to negate it.
|
||||||
|
|
||||||
|
## Working with Git Repositories
|
||||||
|
|
||||||
|
Clone a git repo:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
arc clone <url> [path]
|
||||||
|
```
|
||||||
|
|
||||||
|
Migrate an existing git repo (run inside the repo):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
arc migrate
|
||||||
|
```
|
||||||
65
docs/git-bridge.md
Normal file
65
docs/git-bridge.md
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Git Bridge
|
||||||
|
|
||||||
|
Arc uses an internal git bridge to interoperate with git remotes. Since Arc uses its own delta-based storage format (ZSTD-compressed MessagePack), it maintains a shadow bare git repository to translate between formats when communicating with git servers.
|
||||||
|
|
||||||
|
## Shadow Repository
|
||||||
|
|
||||||
|
- Located at `.arc/git/` — a bare git repository created automatically on first use.
|
||||||
|
- A bidirectional mapping between arc commit IDs and git OIDs is stored in `.arc/git-map.yml`.
|
||||||
|
- The map has two fields: `arc_to_git` and `git_to_arc`, both string-to-string mappings.
|
||||||
|
|
||||||
|
## Commit Conversion
|
||||||
|
|
||||||
|
**Arc → Git:** The bridge materializes the full file tree at each arc commit, writes it as a git tree object, and creates a git commit with the same message, author, and timestamp. Parents are recursively converted. Cached mappings are reused.
|
||||||
|
|
||||||
|
**Git → Arc:** The bridge reads the git tree, computes deltas against the parent's tree using Arc's `detect_changes`, and creates arc `CommitObject` entries. Author info and timestamps are preserved from the git commit.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
- SSH authentication is attempted first via the SSH agent, then by scanning `~/.ssh/` for key files (`id_ed25519`, `id_rsa`, `id_ecdsa`).
|
||||||
|
- Interactive/password authentication is not supported.
|
||||||
|
- Up to 4 authentication attempts are made before failing.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### Push (`arc push [-r remote]`)
|
||||||
|
|
||||||
|
- Converts all arc commits on the current bookmark to git commits.
|
||||||
|
- Pushes the current bookmark as a git branch to the remote.
|
||||||
|
- Only pushes the active bookmark's branch.
|
||||||
|
- Uses fast-forward only; diverged histories produce an error.
|
||||||
|
- Default remote is `origin` (configurable via `default.remote`).
|
||||||
|
|
||||||
|
### Pull (`arc pull [-r remote]`)
|
||||||
|
|
||||||
|
- Fetches from the remote into the shadow git repo.
|
||||||
|
- Converts new git commits to arc commits.
|
||||||
|
- Fast-forward only — if the local bookmark has diverged, an error is returned.
|
||||||
|
- Updates the bookmark pointer and worktree.
|
||||||
|
|
||||||
|
### Clone (`arc clone [-b branch] <url> [path]`)
|
||||||
|
|
||||||
|
- Clones the git remote into a new arc repository.
|
||||||
|
- Imports all branches as bookmarks and tags.
|
||||||
|
- Checks out the specified branch (or the remote HEAD, or `main` by default).
|
||||||
|
- Writes the full worktree after import.
|
||||||
|
|
||||||
|
### Migrate (`arc migrate`)
|
||||||
|
|
||||||
|
- Converts an existing git repository (in the current directory) to an arc repository.
|
||||||
|
- Creates `.arc/` alongside the existing `.git/`.
|
||||||
|
- Imports all `refs/heads/*` as bookmarks and `refs/tags/*` as tags.
|
||||||
|
- Preserves remotes from the git config.
|
||||||
|
- Sets HEAD to the same branch as the git repo's HEAD.
|
||||||
|
|
||||||
|
### Sync (`arc sync [-p]`)
|
||||||
|
|
||||||
|
- Ensures the shadow git repo mirrors all arc bookmarks and tags.
|
||||||
|
- Converts any new arc commits to git commits and updates git refs.
|
||||||
|
- With `-p` (`--push`), also pushes all refs to the default remote.
|
||||||
|
|
||||||
|
## Remotes
|
||||||
|
|
||||||
|
- Stored in `.arc/remotes.yml` as a YAML map of name → URL.
|
||||||
|
- Managed with `arc remote add|rm|list`.
|
||||||
|
- When pushing to git, bookmarks become git branches and tags become git tags.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue