# xit mixes patch based merging with snapshot storage in Zig

> xit is a version control system written in Zig that speaks the git networking protocol for clone, fetch and push while using patch based merging like Darcs or Pijul and snapshot storage like git, with a built in terminal interface and a reimplementation of git in pure Zig. It suits a developer experimenting with version control design, and it is young enough that a core command is still missing.

**xit-vcs/xit** — a git alternative written in zig

- Repository: https://github.com/xit-vcs/xit
- Website: https://xit-vcs.github.io/xitlog
- Stars: 737 · Forks: 18
- Language: Zig
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/xit-vcs-xit

## Git on the wire, something else on disk

xit is a version control system written in Zig, and the design decision that defines it is a split between the network protocol and the storage model. The project is git compatible in the sense that it uses the git networking protocol for push, fetch and clone, and it supports http, ssh, the raw git protocol and local remotes, with details in docs/compat.md. Underneath that wire format is a different data model, because xit combines snapshot based and patch based version control. Merging and cherry-picking uses patches like Darcs and Pijul, while restoring files and anything sent over the network uses snapshots like git, and docs/patch.md explains the difference. The practical effect is that a merge in xit is a three way style reconciliation of changes rather than a diff of two trees, which is the property that makes Darcs and Pijul pleasant to use and that git has spent a decade trying to approximate with rerere and criss-cross merges. It is also the property most likely to behave differently from what a git user expects.

## A command set that mirrors git, minus pull

The README prints the full help output, which is the fastest way to see the shape of the tool. The commands are init, patch to enable or disable patch based merging, add, unadd, untrack, rm, commit, tag, status, diff, diff-added, branch, switch, reset in its three forms of reset, reset-dir and reset-add, restore, log, merge, cherry-pick, config, remote, gc, clone, fetch, push, upload-pack, receive-pack and http-backend. Several of them are annotated with their git equivalent, which tells you how carefully the author is matching behaviour. unadd is similar to git reset HEAD, untrack is similar to git rm --cached, rm does both, diff-added is similar to git diff --cached, reset-dir is similar to git reset --hard, and reset-add is like calling reset and then adding everything to the index, similar to git reset --soft. The reset family having three separate commands is a design choice rather than an oversight, and it is the clearest sign that this author treats the index as a first class object. One gap is stated outright. I still need to implement pull, but for now you can combine fetch and merge to get the same effect:

```bash
xit fetch origin
xit merge refs/remotes/origin/master
```

## The TUI is the main interface, and it includes undo

Launching xit in a repository with no arguments opens a built in terminal user interface, and the README says the TUI currently shows log, status, config and undo, with more detail in docs/tui.md. The screenshot in the documentation shows a four panel layout with a log on the left, a diff on the right and tabs along the top, and the escape key quits. The undo panel is the interesting part, because it points at the universal undo feature. Any change to the repository can be cleanly undone from the TUI, and the undo history can be cleared to recover space with xit gc. The git gc command is documented in the help output as reclaiming disk space by removing objects unreachable from any branch, tag or index and compacting the database files, which is the same job git gc does, and the difference is that here the undo history is something you can clear deliberately once you are satisfied with a state. That is a real workflow difference, because a git user who wants to drop the safety net has to think about reflog expiry and gc pruning rules.

## Large and binary files are chunked, not compressed

The storage layer handles large files in a way worth understanding, because file size is where version control systems usually become painful. xit uses a modern chunking algorithm, FastCDC, to deltify large files, and it does not compress files that don't benefit from it. Content defined chunking is the technique that lets a file split into pieces determined by its own content rather than by fixed offsets, so an insertion in the middle of a file only changes the chunks after it instead of shifting everything, which is what makes deltas against a similar earlier version of the same file meaningful. The other half of the decision is the refusal to compress files that would not compress well, which avoids spending CPU and space on binaries that deflate poorly. Both choices are described in docs/chunk.md. For a repository holding large media or compiled artefacts alongside source, that is the difference between a store that stays small and one that grows without limit, and it is also the reason the implementation is self-contained rather than built on an existing chunker.

## No third-party libraries, and git reimplemented in Zig

The implementation stance is stated bluntly: the project uses no third-party libraries in production, and all bugs are our bugs. That is a claim about dependency risk as much as about pride, and it has an obvious cost, because every algorithm is in-tree and has to be maintained by the project. The counterweight is reuse. xit can be easily used as a library in other projects, and it contains a reusable git implementation in pure Zig, with docs/lib.md describing xit's internals and how to use it as a library. The README names a real user of that interface, Haxy, which is described as using xit as a library rather than as a command line tool. The library angle is the more interesting of the two for a Zig developer, because the same repository that gives you a version control system also gives you a git implementation you can link into something else. The work here is Zig, the build file is build.zig, and the build configuration is build.zig.zon.

## Getting it running, and the state of the project

The build is short. Install zig 0.17.0, run zig build in the repository, and the binary appears at zig-out/bin/xit. The CLI is close enough to git that the example session reads like a git tutorial:

```bash
xit init test
cd test
echo hello > readme.md
xit add readme.md
xit commit -m "hello world"
```bash

Branching and merging work the way you would expect, with xit branch add stuff, xit branch list, xit switch stuff, a second commit, xit switch master and xit merge stuff. Cloning and pushing to a git remote over http or ssh works as well, with xit clone, xit add, xit commit and xit push origin master. Conversion in both directions is done with local remotes, so you can move a repository from git to xit with xit clone path/to/git/repo path/to/xit/repo, and from xit to git with git init, xit remote add and xit push. The project is not archived, the last push was on 2026-10-15, and the licence is MIT. There are no GitHub releases, so the commit is the version marker, and the fact that pull is unfinished is a fair signal of where the project stands.

## Conclusion

Adopt xit when you want to experiment with a version control design that merges patches rather than snapshots, or when you want to embed a version control implementation in a Zig program through its library interface. Do not adopt it as a daily driver yet, since the documentation says pull is still to be implemented and there are no GitHub releases to pin. Verify first that the git compatibility work in docs/compat.md covers the operations your workflow needs, that your Zig toolchain matches the required 0.17.0, and that the branch and merge semantics documented in docs/patch.md behave the way your team expects before you migrate any history.

## FAQ

### How is xit compatible with git?

It uses the git networking protocol for push, fetch and clone, and supports http, ssh, the raw git protocol and local remotes, with the details in docs/compat.md. The storage model differs, since merging and cherry-picking use patches like Darcs and Pijul while restoring files and network transfers use snapshots like git.

### How do I build and try xit?

Install zig 0.17.0, run zig build in the repository, and the binary is at zig-out/bin/xit. A first repository is xit init test, then cd test, echo hello to a file, xit add, and xit commit with a message.

### Does xit support pull?

Not yet. The documentation states that pull still needs to be implemented and that for now you can combine fetch and merge to get the same effect, with xit fetch origin followed by xit merge refs/remotes/origin/master.

### How does xit handle large and binary files?

It uses FastCDC, a content defined chunking algorithm, to deltify large files, and it does not compress files that do not benefit from it. The reasoning is in docs/chunk.md, and the goal is a store that stays small for repositories holding media or build artefacts.

## Sources

- [Issues](https://github.com/xit-vcs/xit/issues)
- [License: MIT](https://github.com/xit-vcs/xit/blob/master/LICENSE)
- [Project website](https://xit-vcs.github.io/xitlog)
- [README](https://github.com/xit-vcs/xit/blob/master/README.md)
- [xit-vcs/xit on GitHub](https://github.com/xit-vcs/xit)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/xit-vcs-xit
