Skip to content
Pure Elixir native implementation of git
Branch: master
Clone or download
scouten Implement Xgit.ConfigEntry. (#283)
This struct describes a single line in a config file or similar storage mechanism.
Latest commit 4bcc2eb Jan 11, 2020
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Run mix credo and mix format --check-formatted separately. (#221) Nov 15, 2019
bench [API BREAKING] Move index file format parsing into Xgit.DirCache modu… Dec 15, 2019
branding Fix Xgit logo. (#95) Aug 17, 2019
config Force code coverage for cases where a literal value is returned. (#122) Sep 1, 2019
lib Implement Xgit.ConfigEntry. (#283) Jan 11, 2020
test Implement Xgit.ConfigEntry. (#283) Jan 11, 2020
.credo.exs Set Credo to require @specs. (#12) Jul 14, 2019
.dialyzer_ignore.exs Silence the dialyzer unimplemented protocol errors. (#81) Aug 15, 2019
.formatter.exs First benchmark: Looking at Xgit.Repository.WorkingTree.ParseIndexFil… Sep 17, 2019
.gitignore Revert "Add .elixir_ls to .gitignore. (#113)" (#117) Aug 23, 2019
LICENSE Initial project skeleton. Jul 12, 2019 Avoid the mix deps.get and mix deps.compile steps via cache. (#220) Nov 15, 2019
coveralls.json Initial project skeleton. Jul 12, 2019
mix.exs Implement Xgit.ConfigEntry. (#283) Jan 11, 2020
mix.lock Bump excoveralls from 0.12.0 to 0.12.1 (#234) Nov 26, 2019

Xgit Xgit

Pure Elixir native implementation of git

Build Status Code Coverage Hex version API Docs License badge


This is very much a work in progress and not ready to be used in production. What is implemented is well-tested and believed to be correct and stable, but much of the core git infrastructure is not yet implemented. There has been little attention, as yet, to measuring performance.

For information about the progress of this project, please see the Xgit Reflog (blog).

Where Can I Help?

This version of Xgit replaces an earlier version which was a port from the Java implementation of git, jgit. In coming days/weeks, I'll share more about the new direction and where help would be most welcome.

For now, please see:

Why an All-Elixir Implementation?

With all of git already implemented in libgit2, why do it again?

I considered that, and then I read Andrea Leopardi:

NIFs are dangerous. I bet you’ve heard about how Erlang (and Elixir) are reliable and fault-tolerant, how processes are isolated and a crash in a process only takes that process down, and other resiliency properties. You can kiss all that good stuff goodbye when you start to play with NIFs. A crash in a NIF (such as a dreaded segmentation fault) will crash the entire Erlang VM. No supervisors to the rescue, no fault-tolerance, no isolation. This means you need to be extremely careful when writing NIFs, and you should always make sure that you have a good reason to use them.

libgit2 is a big, complex library. And while it's been battle-tested, it's also a large C library, which means it takes on the risks cited above, will interfere with the Erlang VM scheduler, and make the build process far more complicated. I also hope to make it easy to make portions of the back-end (notably, storage) configurable; that will be far easier with an all-Elixir implementation.


Xgit is heavily influenced by jgit, an all-Java implementation of git. Many thanks to the jgit team for their hard work. Small portions of Xgit are based on an earlier port from Java to Elixir; those files retain the original credits and license from the jgit project.

You can’t perform that action at this time.