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:
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-buster-jfpactjnem.now.sh/github.com/wmhilton/isomorphic-git')
git('.').init()
git('.')
.setConfig('remote.origin.url', 'https://cors-buster-jfpactjnem.now.sh/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('.')
.author('Mr. Test')
.email('mrtest@example.com')
.signingKey('-----BEGIN PGP PRIVATE KEY BLOCK-----...')
.commit('Added the a.txt file')
git('.')
.auth(process.env.GITHUB_TOKEN)
.remote('origin')
.push('refs/heads/master')
git('.').auth('username', 'password')
git('.').auth('username:password')
git('.').auth('username', 'personal access token')
git('.').auth('username', 'app password')
git('.').auth('personal access token')
git('.').oauth2('github', 'token')
git('.').oauth2('gitlab', 'token')
git('.').oauth2('bitbucket', 'token')
git().findRoot('/path/to/some/gitrepo/path/to/some/file.txt')
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
Lower-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 have written this library
as a series of layers that should tree-shake very well:
- index.js (~5kb uncompressed)
- commands.js (~19kb uncompressed)
- managers.js (~11kb uncompressed)
- models.js (~19kb uncompressed)
- utils.js (~11kb uncompressed)
Commands
import * as managers from 'isomorphic-git/dist/for-node/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/dist/for-node/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/dist/for-node/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/dist/for-node/utils'
I lied. Utils are actually the lowest level building blocks.