What is isomorphic-git?
isomorphic-git is a pure JavaScript implementation of Git that works in both Node.js and browser environments. It provides a wide range of Git functionalities, allowing developers to perform Git operations without relying on native Git installations.
What are isomorphic-git's main functionalities?
Clone a Repository
This feature allows you to clone a Git repository. The code sample demonstrates how to clone the isomorphic-git repository into a local directory named '/tutorial'.
const git = require('isomorphic-git');
const fs = require('fs');
(async () => {
await git.clone({
fs,
dir: '/tutorial',
url: 'https://github.com/isomorphic-git/isomorphic-git',
singleBranch: true,
depth: 1
});
console.log('Cloned the repository!');
})();
Commit Changes
This feature allows you to commit changes to a repository. The code sample demonstrates how to commit changes in the '/tutorial' directory with a commit message 'Initial commit'.
const git = require('isomorphic-git');
const fs = require('fs');
(async () => {
await git.commit({
fs,
dir: '/tutorial',
author: {
name: 'Your Name',
email: 'you@example.com'
},
message: 'Initial commit'
});
console.log('Committed changes!');
})();
Push to Remote
This feature allows you to push changes to a remote repository. The code sample demonstrates how to push changes from the '/tutorial' directory to the 'main' branch of the remote repository 'origin'.
const git = require('isomorphic-git');
const fs = require('fs');
(async () => {
await git.push({
fs,
dir: '/tutorial',
remote: 'origin',
ref: 'main',
token: 'your-github-token'
});
console.log('Pushed to remote!');
})();
Fetch from Remote
This feature allows you to fetch changes from a remote repository. The code sample demonstrates how to fetch changes from the 'origin' remote repository into the '/tutorial' directory.
const git = require('isomorphic-git');
const fs = require('fs');
(async () => {
await git.fetch({
fs,
dir: '/tutorial',
remote: 'origin'
});
console.log('Fetched from remote!');
})();
List Files in a Commit
This feature allows you to list files in a specific commit. The code sample demonstrates how to read the commit object for the 'HEAD' commit and log the tree of files.
const git = require('isomorphic-git');
const fs = require('fs');
(async () => {
const commit = await git.readCommit({
fs,
dir: '/tutorial',
oid: 'HEAD'
});
console.log(commit.commit.tree);
})();
Other packages similar to isomorphic-git
nodegit
NodeGit is a native Node.js binding to the libgit2 library, providing a comprehensive set of Git functionalities. Unlike isomorphic-git, NodeGit relies on native bindings and is not designed to work in browser environments.
simple-git
Simple-git is a lightweight wrapper around the Git command line interface, providing a simple API for common Git operations. It requires Git to be installed on the system and is not designed to work in browser environments, unlike isomorphic-git.
dugite
Dugite provides a simplified interface for using Git in Node.js applications. It bundles a specific version of Git with the package, ensuring consistent behavior across different environments. However, it does not support browser environments like isomorphic-git.
isomorphic-git
JavaScript library for interacting with git repositories, circa 2017
(Originally I was going to call it esgit
but the name is too similar to another
project called es-git.)
Progress
Porcelain:
Plumbing:
Note: There appears to be no a way to push signed commits back to Github using their API (v3 or v4), so I think we will have to use smart HTTP, packfiles, and an anti-CORS proxy.
High-level API (unstable)
This is analogous to the "porcelain" git commands. There is a single function git()
that serves as a fluent command builder.
Examples:
import git from 'isomorphic-git'
git('.')
.depth(1)
.branch('master')
.clone('https://cors-anywhere.herokuapp.com/https://github.com/wmhilton/isomorphic-git')
git('.').init()
git('.')
.setConfig('remote.origin.url', 'https://cors-anywhere.herokuapp.com/https://github.com/wmhilton/isomorphic-git')
git('.')
.remote('origin')
.depth(1)
.fetch('refs/heads/master')
git('.').checkout('master')
git('.').list()
git('.').add('README.md')
git('.').remove('.env')
git('.')
.add('a.txt')
.author('Mr. Test')
.email('mrtest@example.com')
.signingKey('-----BEGIN PGP PRIVATE KEY BLOCK-----...')
.commit('Added the a.txt file')
git('.')
.githubToken(process.env.GITHUB_TOKEN)
.remote('origin')
.push('refs/heads/master')
git().gitdir('my-bare-repo').workdir('/var/www/website')
CLI
I realized I could "translate" command line options into JavaScript chained commands
without hard-coding any knowledge of the API if I kept the chained commands very predictable.
I built a purely a generic translator and it worked surprisingly well.
So you can do any current or future isomorphic-git commands using the included esgit
CLI.
It always starts with an implicit git('.')
so it defaults to working in the
current working directory.
// Create a new empty repo
esgit --gitdir=test init
// Clone from a Github repository to the current working directory.
// Just like it's counterpart, clone is really just shorthand for git.init(); git.fetch(); git.checkout();
esgit clone https://github.com/wmhilton/isomorphic-git
// Checkout a commitish
esgit checkout master
// List files in the index
esgit list
// Add files to the index
esgit add README.md
// Remove files from the index
esgit remove .env
// Create a new commit (there's actually several more options for date, committer)
esgit add a.txt
esgit --author='Mr. Test' --email=mrtest@example.com --signingKey="$(cat private.key)" commit 'Added the a.txt file'
// And if you need to work with bare repos there are
// equivalents to the `--git-dir` and `--work-tree` options
esgit --gitdir=my-bare-repo --workdir=/var/www/website
Low-level API (also unstable)
The high-level makes some assumptions (like you have a file-system and network access) that might not be well suited
to your embedded git-based concept thingy. Fear not! I am
purposefully building this library as a series of small modules
so you can pick and choose features as you need them.
Commands
import * as managers from 'isomorphic-git/src/commands'
Each command is available as its own file, so hopefully with
a bit of finagling you will be able to import individual commands
if you only need a few and can benefit from tree-shaking.
Managers
import * as managers from 'isomorphic-git/src/managers'
Managers are a level above models. They take care of implementation performance details like
- batching reads to and from the file system
- in-process concurrency locks
- lockfiles
- caching files and invalidating cached results
- reusing objects
- object memory pools
Models
import * as models from 'isomorphic-git/src/models'
Models are the lowest level building blocks.
They generally have very few or no dependencies except for 'buffer'
.
This makes them portable to many different environments so they can be a useful lowest common denominator.
Utils
import * as utils from 'isomorphic-git/src/utils'
I lied. Utils are actually the lowest level building blocks.