git #
Warning. This is a work-in-progress experimental fork of ocaml-git. Do not use it in production; use ocaml-git instead.
Git in pure OCaml: objects, packs, repositories and the smart protocol.
The smart protocol is git's native transfer protocol over HTTP or SSH: the two sides exchange the references and object hashes they hold, and the server then sends one pack file holding only the objects the client lacks.
Tools that manage many repositories at once, such as a monorepo that splits
and merges subtrees, spend most of their time spawning git and parsing its
output, and they fight over index.lock when two of them work in one
checkout. This package reads and writes git's own formats directly instead:
loose objects, pack files and their indexes, bitmaps, references and
configuration. On top of that it implements the operations such tools need
(clone, fetch, push, pull, checkout, merge, diff, history rewriting and
subtree split) and a smart-protocol server that a stock git client can
clone from. The object code is derived from ocaml-git and carton; the
rest is newer and has had far less use.
The code is split into four opam packages:
nox-git: the formats, and the repository operations as functors over an abstract object store (Git.Store.S), with no I/O of their own;nox-git-eio: those operations over a repository on disk, using Eio (Git_eio.Repository,Git_eio.Subtree,Git_eio.Rewrite, and so on);nox-git-net: fetch, push and clone over smart HTTP and SSH, with a smart-HTTP server innox-git-net.serverand SSH fetch, push and serving innox-git-net.ssh;git-x: a command-line tool built on the three libraries.
Installation #
Install with opam:
$ opam install nox-git
If opam cannot find the package, it may not yet be released in the public
opam-repository. Add the overlay repository, then install it:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install nox-git
Usage #
Build a blob, a tree holding it and a commit of that tree, and compute their object hashes without touching a repository:
open Git
(* Create a blob *)
let blob = Blob.of_string "Hello, World!\n"
let blob_hash = Blob.digest blob
(* Create a tree entry *)
let entry = Tree.entry ~perm:`Normal ~name:"hello.txt" blob_hash
let tree = Tree.v [ entry ]
let tree_hash = Tree.digest tree
(* Create a commit *)
let author = User.v ~name:"Alice" ~email:"alice@example.com"
~date:(Int64.of_float (Unix.gettimeofday ())) ()
let commit = Commit.v
~tree:tree_hash
~author
~committer:author
(Some "Initial commit")
Command-line tool (git-x) #
git-x runs git operations for monorepos natively: it reads objects
directly instead of spawning git, and it updates references atomically, so
it can run while other people or tools edit the same checkout. Its main
commands are:
git-x status [-v] DIRshows working-tree and upstream status for every repository underDIR. With-v, a modified OCaml file also lists the definitions whose source differs fromHEAD, by address (:Module.value), using thenox-git.outlinelibrary. A changed submodule is shown by its changed members.git-x commit create -m MSG PATH...commits the working-tree state of the named paths straight into the object database, without reading or writing the index. It never picks up files someone else staged and never waits onindex.lock; afterwards it refreshes the index entries of the committed paths so thatgit statusshows them clean.git-x commit drop|reword|sort|squash|split SHArewrites one commit in history and leaves the working tree andHEADalone.git-x tree split PREFIXextracts the history of a subdirectory as a standalone commit chain. The result is cached, so running it again costs almost nothing.git-x tree graft --prefix DIR REVis the inverse. It replays a standalone chain underDIRas ordinary single-parent commits, one commit out for each chain commit in, so splitting the result back out gives the same chain, hash for hash. It records how far it has got inrefs/graft/<DIR>instead of testing ancestry, so a second run replays nothing and the result does not depend on the shape of either history. Paths the chain does not touch are left alone, andHEAD, the working tree and the index move together.git-x tree add|drop|check|fix|verifyare the other subtree operations.git-x clone,fetch,pullandpushtalk to remotes over smart HTTP and SSH, andgit-x serveserves a repository to them.
$ git-x status -v
. (main) dirty
M lib/parser.ml
:Lexer.token
:parse
Credits #
The object and pack code is a simplified rewrite derived from:
- ocaml-git, the git format and protocol in pure OCaml, by Thomas Gazagnaire and Romain Calascibetta;
- carton, the PACKv2 implementation, by Romain Calascibetta.
License #
ISC. See LICENSE.md.