Patchwork is a peer-to-peer version control system inspired by Git.
Repositories synchronize directly between peers without using a central server.
Patchwork is used through a command-line interface and follows a Git-like workflow.
All commands are executed inside a project directory or any of its subdirectories.
Patchwork automatically finds the repository by locating a .patch directory in parent folders.
Initializes a new Patchwork repository in the current directory.
When this command is executed, Patchwork first checks whether a .patch directory already exists in the current directory or any parent directory. If a repository is found, initialization is aborted to prevent overwriting an existing repository.
If no repository exists, the command performs the following steps:
- Creates a
.patchdirectory in the current project root. - Creates the object store directories
.patch/objects/blobs,.patch/objects/trees, and.patch/objects/commits. - Initializes a new repository configuration using the provided name as the author identity.
- Generates a new cryptographic peer identity and derives a peer endpoint from it.
- Stores the generated secret key and endpoint identifier in the repository configuration.
- Writes the initial configuration to
.patch/patchwork.toml.
After successful initialization, the directory is ready to be used as a Patchwork repository and can immediately participate in peer-to-peer synchronization.
Initializes a new local Patchwork repository by connecting to an existing peer and bootstrapping collaboration.
When this command is executed, Patchwork performs the following steps:
- Verifies that no
.patchdirectory exists in the current directory or any parent directory to avoid overwriting an existing repository. - Creates a new
.patchdirectory and initializes the local object store, including subdirectories for blobs, trees, and commits. - Initializes a fresh local configuration and generates a new cryptographic peer identity.
- Derives a local peer endpoint from the generated secret key.
- Connects to the remote peer specified by
<peer-public-key>(endpoint of a peer) using the clone protocol. - Receives a redacted repository configuration from the remote peer, containing repository metadata and collaborator information while excluding private key material.
- Registers the remote peer as a collaborator in the local configuration.
- Sends an explicit acknowledgment (
ACK) to complete the clone handshake. - Writes the initialized configuration to
.patch/patchwork.toml.
The clone command only bootstraps metadata and peer relationships. No commits, trees, or blobs are transferred during cloning. Repository contents are synchronized later using pull and push commands.
Stages files for the next commit by creating content-addressed blob objects.
The add command prepares files to be included in the next commit. It reads file
contents, stores them as immutable blob objects, and records their hashes in the
staging area.
When patchwork add (path) is executed, Patchwork performs the following steps:
- Locates the Patchwork repository.
- Loads the repository configuration.
- Resolves paths relative to the project root.
- Processes all provided file paths.
For each file path, Patchwork:
- Checks that the path exists and refers to a regular file
(directories are not supported yet). - Reads the complete file content into memory.
- Computes a SHA-256 content hash using a Git-style blob header consisting of:
- the object type (
blob), - the file size,
- a null separator,
- the raw file bytes.
- the object type (
- Stores the file content as a blob object at
.patch/objects/blobs/<hash>. - Skips writing the blob if an identical blob already exists (content-based deduplication).
- Converts the absolute file path into a path relative to the project root.
- Adds an entry to the staging area mapping
relative/path/to/file -> blob hash.
After all files have been processed, the updated staging area is written back to
patchwork.toml.
Files staged with patchwork add become part of the next snapshot when
patchwork commit is executed.
Creates a new commit representing a complete snapshot of the project state.
The commit command takes the files prepared with patchwork add and produces
an immutable snapshot of the repository. While commits are built incrementally
from previous ones, each commit fully describes the project state via its root
tree.
When patchwork commit is executed, Patchwork performs the following steps:
- Loads the repository configuration.
- Verifies that the staging area is not empty.
- Resolves the parent commit (if one exists).
- Reconstructs the previous root tree from the parent commit.
- Applies the staged file changes onto that tree.
- Writes a new root tree object representing the full project snapshot.
- Creates a commit object containing:
- the new root tree hash,
- the parent commit hash (if any),
- the author name,
- the commit message,
- a timestamp.
- Stores the commit as a content-addressed object.
- Updates
last_committo reference the new commit. - Clears the staging area.
- Persists the updated configuration to
patchwork.toml.
Although a commit is derived by applying changes to the previous tree, the resulting commit always represents a complete snapshot and can be reconstructed independently using its root tree hash.
Starts the local Patchwork peer server.
This command is used to enable peer-to-peer collaboration. It loads the existing repository configuration and starts listening for incoming connections from other peers.
When running patchwork start:
- The repository configuration is loaded from
.patch/patchwork.toml. - The stored peer identity is used to initialize the local peer.
- The peer server is started and listens for incoming clone, pull, and push requests.
- The process keeps running until it is manually stopped.
The peer server must be running in order for other peers to clone the repository or exchange updates via pull and push.
Fetches and integrates missing commits and objects from one or more peers.
The pull command synchronizes the local repository with remote peers using an incremental, history-based protocol. It compares commit histories and transfers only the data that is not already present locally.
When patchwork pull is executed, the following steps are performed:
- Loads the local repository configuration and verifies that a peer endpoint is configured.
- Determines which peers to pull from:
- If a
<peer-public-key>(endpoint of a peer) is provided, only that peer is contacted. - If no peer is specified, all known collaborators are contacted.
- If a
- Checks whether each peer is reachable using a lightweight handshake.
- Initiates a pull connection to each reachable peer.
For each connected peer, Patchwork performs an incremental synchronization:
- The remote peer sends its latest commit hash.
- The local peer replies with:
yayif the commit already exists locally, ornayif the commit is missing.
- If the commit is missing, the remote peer walks backwards through its parent commits until a common ancestor is found.
- Only the commits that are missing locally are selected for transfer.
- For each missing commit:
- The commit object is transferred.
- All tree objects required to reconstruct the directory snapshot are transferred.
- All referenced blob objects (file contents) are requested and transferred.
After receiving all objects:
- The commit, tree, and blob objects are written into the local object store.
- The local
last_commitpointer is updated to the newest received commit. - The updated configuration is persisted to
patchwork.toml.
If no new commits are found, the pull operation terminates without modifying the repository.
The pull command allows Patchwork repositories to stay synchronized while minimizing network traffic by transferring only missing history and objects.
Sends local commits and objects to all known collaborators.
The push command propagates the local repository state to remote peers. It uses an incremental protocol to ensure that only commits and objects missing on the remote side are transferred.
When patchwork push is executed, Patchwork performs the following steps:
- Locates the Patchwork repository and loads the configuration from
.patch/patchwork.toml. - Collects all configured collaborators from the repository configuration.
- Excludes the local peer from the list of push targets.
- Connects to each collaborator using the push protocol.
For each connected peer, Patchwork performs an incremental push:
- Sends the hash of the local latest commit.
- The remote peer replies with:
yayif the commit already exists, ornayif the commit is missing.
- If the commit is missing, Patchwork walks backwards through the local commit history until a common ancestor is found.
- Only the commits that the remote peer does not yet have are selected for transfer.
- For each selected commit:
- The commit object is sent.
- All tree objects required to reconstruct the directory snapshot are sent.
- All referenced blob objects (file contents) are transferred on demand.
After the transfer completes:
- The remote peer updates its
last_commitpointer. - The local peer prints a per-collaborator push result, including success or error information.
If no collaborators are configured, or if all peers are already up to date, the push operation terminates without transferring data.
The push command ensures efficient peer-to-peer synchronization by avoiding redundant data transfer and only pushing missing repository history.
Restores the working directory to the state of a specific commit snapshot.
The checkout command reconstructs the working directory from the tree
referenced by a commit. Each checkout fully rebuilds the file hierarchy
from stored tree and blob objects, ensuring the working directory matches
the exact snapshot recorded in the commit.
If no commit hash is provided, Patchwork checks out the current last_commit.
When patchwork checkout is executed, Patchwork performs the following steps:
- Loads the repository configuration.
- Resolves the target commit:
- uses the provided commit hash, or
- falls back to
last_commitif none is given.
- Verifies that the commit exists locally.
- Reads the root tree hash from the commit object.
- Reconstructs the full tree structure from stored tree objects.
- Recursively restores the working directory by:
- creating directories for tree entries,
- writing files by copying blob contents from the object store.
- Writes all files relative to the project root.
The checkout process does not apply diffs or incremental changes. Instead, the working directory is rebuilt directly from the commit’s root tree, guaranteeing an exact and reproducible snapshot of the project state.
Branch-based checkout is not yet implemented.
cargo install --path ./
patchwork init alice
mkdir src
echo 'fn main() { println!("Hello from Patchwork"); }' > src/main.rs
patchwork add src/main.rs
patchwork commit "Add initial main file"
patchwork start
patchwork clone
patchwork pull
patchwork checkout
echo '// change by peer 2' >> src/main.rs
patchwork add src/main.rs
patchwork commit "Update main file from peer 2"
patchwork push
patchwork checkout