js-git: A Modular Git Implementation in JavaScript
A JavaScript implementation of Git.
At a glance
- What is it?
- js-git is a JavaScript library that implements Git data structures and operations through a composable mixin architecture. It was built to enable Git-powered applications in environments where native Git is unavailable, such as Chromebooks, tablets, and browser apps, as well as for using Git objects as a general-purpose data store.
- Who is it for?
- js-git suits developers who need Git object operations in a JavaScript environment where native Git binaries cannot run, such as browser applications or restricted platforms. It is not a replacement for the Git command-line tool and does not include a transport layer for cloning from remote repositories in its core.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 103 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The Original Purpose: Git in Constrained Environments
js-git was created to solve a specific problem: developers on Chromebooks, tablets, and other restricted environments cannot run native Git binaries. A JavaScript implementation of Git's core data model can run anywhere a JavaScript runtime exists, including the browser.
The README also identifies a second use case: using Git as a database. Because Git stores content-addressed objects (blobs, trees, and commits), it can replace SQL or NoSQL data stores in applications where content history, branching, or immutable object identity are valuable properties.
The project version is 0.7.8 as listed in `package.json`. The last push was on 2026-06-20. It is licensed under MIT.
Two crowd-sourced fundraisers originally funded the project. The `BACKERS.md` and `BACKERS-2.md` files in the repository record contributors from those campaigns.
The Mixin Architecture: Building a Repo Object
js-git does not use class inheritance. Instead, it creates a plain JavaScript object and applies functionality through mixins. Each mixin adds specific methods to the repo object. This makes it possible to compose only the features needed for a given use case.
A minimal in-memory repository uses three mixins:
var modes = require('js-git/lib/modes');
var repo = {};
require('js-git/mixins/mem-db')(repo);
require('js-git/mixins/create-tree')(repo);The `mem-db` mixin adds `saveAs`, `loadAs`, `saveRaw`, and `loadRaw` methods for storing and retrieving Git objects in memory. The `create-tree` mixin adds a high-level `createTree` method for creating trees by path. Other mixins handle walkers, format helpers, and network operations.
This design means the in-memory storage backend is interchangeable with other backends (filesystem, IndexedDB, remote) without changing application code that calls `repo.saveAs` or `repo.loadAs`.
Creating and Reading Git Objects
The core operations are `saveAs` and `loadAs`, which accept a type string (`"blob"`, `"tree"`, `"commit"`) and a value. Using the `formats` mixin, values can be strings and arrays rather than raw binary buffers.
Creating a blob, tree, and commit in sequence:
var blobHash = yield repo.saveAs("blob", "Hello World\n");
var treeHash = yield repo.saveAs("tree", {
"greeting.txt": { mode: modes.file, hash: blobHash }
});
var commitHash = yield repo.saveAs("commit", {
tree: treeHash
});Reading the file back from the commit:
var commit = yield repo.loadAs("commit", commitHash);
var tree = yield repo.loadAs("tree", commit.tree);
var file = yield repo.loadAs("blob", tree["greeting.txt"].hash);With the `formats` mixin, a file can be loaded as text directly using `"text"` as the type, or a tree can be loaded as an array of entries using `"array"` instead of an object keyed by filename.
Walking History and the Filesystem-Style API
The walkers mixin provides `logWalk` for iterating commit history as a linear stream and `treeWalk` for iterating a file tree in depth-first order:
var logStream = yield repo.logWalk(commitHash);
var commit;
while (commit = yield logStream.read(), commit !== undefined) {
var treeStream = yield repo.treeWalk(commit.tree);
}For creating or modifying multiple files at once, the `create-tree` mixin provides a higher-level abstraction that accepts a map of paths to file contents:
var treeHash = yield repo.createTree({
"www/index.html": {
mode: modes.file,
content: "<h1>Hello</h1>\n"
},
"README.md": {
mode: modes.file,
content: "# Sample repo\n"
}
});This handles creating intermediate tree objects for nested paths automatically. It also supports modifying existing trees by passing in a base tree hash.
Generator and Callback Control Flow
js-git's async APIs support two control-flow styles. The examples in the README use ES6 generator functions with `yield`, intended to be driven by a runner like gen-run:
var run = require('gen-run');
run(function*() {
var result = yield someAction(withArgs);
});All js-git APIs also support Node.js-style callbacks. When no callback is passed, the function returns a partially applied version expecting only the callback:
someAction(withArgs, function (err, value) {
if (err) return handleMyError(err);
});The dual-style support was designed for compatibility across environments where ES6 generators were not yet stable. At the time the project was built, generators were available in stable Firefox and Chrome behind a flag, and in Node.js 0.11.x with a command-line flag.
Modern JavaScript environments all support generators and async/await, but js-git's API predates async/await and has not been updated to use it natively.
Limitations and Comparison with isomorphic-git
js-git's core is focused on object storage and retrieval. The repository includes a `net/` directory and `mixins/` that cover network operations, but the README does not document a full Git remote protocol implementation. Cloning a repository from a remote server is not described as a built-in operation in the README's API documentation.
The `package.json` lists the dependencies as `bodec` (binary data), `culvert` (streams), `git-sha1` (SHA1 hashing), and `pako` (zlib compression). The library handles the Git object model but does not include HTTPS or SSH transport in its documented core. The `doc/` subdirectory contains API documentation for the available mixins, but the README serves as the primary reference for common operations.
The API was designed around generators and callbacks, both patterns that predate modern `async/await`. Integrating js-git into a codebase that uses `async/await` throughout requires adapter code or wrappers. The `gen-run` runner used in the README examples is a separate npm package not bundled with js-git itself. For environments that cannot use ES6 generators, the callback style provides equivalent functionality without any additional dependencies, since all js-git core APIs support both invocation patterns transparently without any configuration.
isomorphic-git is a more recent JavaScript Git implementation that targets a complete Git command surface, including clone, fetch, push, and pull over HTTPS. It provides a promise-based async API and is designed to work in both Node.js and browsers. The key difference is scope: isomorphic-git aims to replace the Git CLI in JavaScript environments, while js-git focuses on the object model and was designed for embedding in constrained environments with composable storage backends. For applications that need full remote Git protocol support without bridging to a native binary, isomorphic-git is the more complete option.
Editorial conclusion
js-git suits developers who need Git object operations in a JavaScript environment where native Git binaries cannot run, such as browser applications or restricted platforms. It is not a replacement for the Git command-line tool and does not include a transport layer for cloning from remote repositories in its core. Teams that need full remote protocol support should evaluate isomorphic-git instead, which provides a more complete Git command surface. Confirm that js-git's mixin-based API aligns with your application structure before building on it.
Frequently asked questions
Can js-git clone a remote Git repository?
The core documented API in the README covers in-memory object storage, tree walking, and local object creation. The repository includes a net/ directory with network-related mixins, but the README does not document a full clone operation as a built-in feature. isomorphic-git is an alternative that provides clone, fetch, and push over HTTPS.
What JavaScript environments does js-git support?
js-git was originally built to run in environments where native Git is unavailable, including browsers and Chromebooks. It uses no Node.js-specific APIs in its object model. The README discusses ES6 generator support across Firefox, Chrome, and Node.js 0.11.x as the baseline environment at the time of writing.
How do I add persistent storage to a js-git repository?
The in-memory storage backend from js-git/mixins/mem-db stores objects in RAM and is lost when the process ends. The mixin architecture is designed so that other storage backends, such as filesystem or IndexedDB, can be substituted by applying a different storage mixin to the repo object. The README does not document specific persistent backend mixins beyond mem-db.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/creationix-js-git)