isomorphic-git: Pure JavaScript Git
isomorphic-git is a comprehensive, pure JavaScript re-implementation of the Git protocol and repository management, designed to operate seamlessly in both Node.js environments and web browsers. It enables applications to read from, write to, fetch from, and push to Git repositories without requiring any native C++ modules or the system's `git` executable. The current stable version is 1.37.5, with frequent patch releases addressing bug fixes and occasional minor features. The project aims for 100% interoperability with the canonical Git implementation, operating on standard `.git` directories. A key differentiator is its modular API, which allows bundlers like Rollup and Webpack to include only the necessary functions, resulting in smaller application bundles. While the original author has moved on, the project is actively maintained by a community of volunteers who oversee code reviews, issues, and ensure its continued functionality and stability. It ships with TypeScript type definitions, providing a robust development experience.
Common errors
-
Error: ENOENT: no such file or directory, open '...' (or similar file system errors)
cause The provided file system (`fs` object) is not correctly initialized, or the specified directory/file path does not exist or is inaccessible within the virtual file system.fixEnsure your `fs` client is properly set up and points to a valid storage location. Verify directory paths and permissions. For Node.js, make sure initial directories are created (`fs.promises.mkdir(dir, { recursive: true })`). For browsers, confirm `lightning-fs` has initialized its IndexedDB store. -
TypeError: Cannot read properties of undefined (reading 'promises') OR Argument of type 'typeof import("node:fs")' is not assignable to parameter of type 'FsClient'.cause The `fs` object passed to isomorphic-git functions does not conform to the expected `FsClient` interface, particularly lacking the `promises` property or required methods within it.fixEnsure your `fs` client object has a `promises` property that exposes async file system methods (`readFile`, `writeFile`, `mkdir`, `readdir`, `rm`, `stat`, `lstat`). If using TypeScript, explicitly type your `fs` object with `FsClient` to catch mismatches during development. -
Error: Unknown transport 'git://' OR Unsupported protocol: 'ssh://'
cause The `url` provided for operations like `clone` or `fetch` uses a Git protocol (e.g., `git://` or `ssh://`) that isomorphic-git either does not support natively or requires additional setup.fixFor common public repositories, use `https://` URLs. For `ssh://` URLs, you need to configure an `ssh` agent and provide a `url` parameter callback to handle the SSH connection. `git://` is generally not supported.
Warnings
- breaking When upgrading from version 0.x to 1.x, significant breaking changes were introduced to the API. Developers should consult the official release notes for `v1.0.0` to understand the necessary migration steps.
- gotcha isomorphic-git requires a compatible file system abstraction (`fs` object) to perform most operations, as it interacts directly with a virtual or actual '.git' directory. This `fs` object is a mandatory parameter for almost all `isomorphic-git` functions.
- gotcha The project's 'maintenance' status means that while it is actively maintained by volunteers for bug fixes and stability, new features are primarily driven by community contributions. Expecting rapid implementation of new features by maintainers alone may lead to disappointment.
- gotcha isomorphic-git works with 'plain' Git over HTTP(S) and SSH (with proper agent configuration). However, advanced Git features, custom protocols, or specific authentication mechanisms may require additional setup or might not be fully supported out-of-the-box compared to the native Git client.
- gotcha The Node.js `engines` requirement is `>=14.17`. Running isomorphic-git in older Node.js versions might lead to compatibility issues, especially with modern ES module usage and `fs/promises` features.
Install
-
npm install isomorphic-git -
yarn add isomorphic-git -
pnpm add isomorphic-git
Imports
- clone
const clone = require('isomorphic-git').cloneimport { clone } from 'isomorphic-git' - init
import init from 'isomorphic-git'
import { init } from 'isomorphic-git' - log
import { default as log } from 'isomorphic-git'import { log } from 'isomorphic-git' - FsClient
import { FsClient } from 'isomorphic-git'
Quickstart
import { clone } from 'isomorphic-git';
import * as fs from 'node:fs/promises'; // For Node.js. For browser, use lightning-fs or similar.
interface FsClient {
promises: {
readFile(path: string, options?: { encoding?: string; flag?: string }): Promise<string | Buffer>;
writeFile(path: string, data: string | Uint8Array, options?: { encoding?: string; mode?: number | string; flag?: string }): Promise<void>;
mkdir(path: string, options?: { recursive?: boolean }): Promise<string | undefined>;
readdir(path: string): Promise<string[]>;
rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>;
stat(path: string): Promise<fs.Stats>;
lstat(path: string): Promise<fs.Stats>;
// ... other methods as needed by isomorphic-git
};
}
// Create an isomorphic-git compatible file system client using Node's fs/promises
const nodeFsClient: FsClient = {
promises: {
readFile: fs.readFile,
writeFile: fs.writeFile,
mkdir: (path, options) => fs.mkdir(path, { recursive: true, ...options }), // Ensure recursive by default
readdir: fs.readdir,
rm: (path, options) => fs.rm(path, { recursive: true, force: true, ...options }), // Ensure recursive & force by default
stat: fs.stat,
lstat: fs.lstat
}
};
async function performClone() {
const dir = './my-cloned-repo';
console.log(`Cloning into ${dir}...`);
try {
await clone({
fs: nodeFsClient, // Provide the file system client
dir: dir,
url: 'https://github.com/isomorphic-git/isomorphic-git-autotests.git', // A small test repo
ref: 'main',
singleBranch: true,
depth: 1
});
console.log('Repository cloned successfully!');
// You can now read files, commit, etc.
const files = await nodeFsClient.promises.readdir(dir);
console.log('Files in cloned repo:', files);
} catch (error) {
console.error('Error during clone:', error);
}
}
performClone();