A pure JavaScript implementation of git for node and browsers
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Advanced Git operations including merging, stashing, and repository walking.
Merges one or more branches into the current branch.
/**
* Merge branches
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.ours - Our branch (defaults to HEAD)
* @param args.theirs - Their branch to merge
* @param args.fastForward - Allow fast-forward merges
* @param args.noUpdateBranch - Don't update branch pointer
* @param args.dryRun - Simulate merge without changes
* @param args.abortOnConflict - Abort on merge conflicts
* @param args.message - Merge commit message
* @param args.author - Author for merge commit
* @param args.committer - Committer for merge commit
* @param args.signingKey - PGP signing key
* @param args.onSign - Signing callback
* @param args.cache - Cache object
* @returns Promise resolving to merge result
*/
function merge(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
ours?: string;
theirs: string;
fastForward?: boolean;
noUpdateBranch?: boolean;
dryRun?: boolean;
abortOnConflict?: boolean;
message?: string;
author?: PersonObject;
committer?: PersonObject;
signingKey?: string;
onSign?: SignCallback;
cache?: object;
}): Promise<MergeResult>;Usage Examples:
import git from "isomorphic-git";
import fs from "fs";
// Basic merge
const mergeResult = await git.merge({
fs,
dir: "/path/to/repo",
theirs: "feature-branch"
});
if (mergeResult.alreadyMerged) {
console.log("Already up to date");
} else if (mergeResult.fastForward) {
console.log("Fast-forward merge completed");
} else {
console.log("Merge commit created:", mergeResult.oid);
}
// Merge with custom message
await git.merge({
fs,
dir: "/path/to/repo",
theirs: "feature-branch",
message: "Merge feature-branch into main\n\nAdds new functionality for user management"
});
// Dry run merge (test for conflicts)
const dryResult = await git.merge({
fs,
dir: "/path/to/repo",
theirs: "risky-branch",
dryRun: true
});
if (dryResult.conflicts && dryResult.conflicts.length > 0) {
console.log("Merge would have conflicts:", dryResult.conflicts);
} else {
console.log("Merge would succeed");
}Aborts an in-progress merge operation.
/**
* Abort an in-progress merge
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @returns Promise resolving when merge is aborted
*/
function abortMerge(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
}): Promise<void>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
// Abort current merge
await git.abortMerge({
fs,
dir: "/path/to/repo"
});
console.log("Merge aborted - repository restored to pre-merge state");Walks through repository trees with custom logic.
/**
* Walk repository trees
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.trees - Array of tree walkers
* @param args.map - Map function for each file
* @param args.reduce - Reduce function for directories
* @param args.iterate - Iterate function for processing
* @param args.cache - Cache object
* @returns Promise resolving to walk result
*/
function walk(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
trees: Walker[];
map?: (filepath: string, entries: WalkerEntry[]) => any;
reduce?: (parent: any, children: any[]) => any;
iterate?: (entries: WalkerEntry[], children: any[]) => any;
cache?: object;
}): Promise<any>;Usage Examples:
import git, { TREE, WORKDIR, STAGE } from "isomorphic-git";
import fs from "fs";
// Compare working directory with HEAD
const results = await git.walk({
fs,
dir: "/path/to/repo",
trees: [TREE({ ref: "HEAD" }), WORKDIR()],
map: async (filepath, [head, workdir]) => {
if (head && workdir) {
// File exists in both
if (head.oid !== (await workdir.oid())) {
return { filepath, status: "modified" };
}
} else if (head && !workdir) {
return { filepath, status: "deleted" };
} else if (!head && workdir) {
return { filepath, status: "added" };
}
return null;
}
});
const changes = results.filter(r => r !== null);
console.log("Changes detected:", changes);
// Compare two commits
const diff = await git.walk({
fs,
dir: "/path/to/repo",
trees: [TREE({ ref: "main" }), TREE({ ref: "feature-branch" })],
map: async (filepath, [commit1, commit2]) => {
if (commit1 && commit2) {
if (commit1.oid !== commit2.oid) {
return { filepath, type: "modified" };
}
} else if (commit1 && !commit2) {
return { filepath, type: "deleted" };
} else if (!commit1 && commit2) {
return { filepath, type: "added" };
}
return null;
}
});
console.log("Differences between branches:", diff.filter(d => d));Stashes working directory changes.
/**
* Stash working directory changes
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.message - Stash message
* @param args.author - Author information
* @param args.cache - Cache object
* @returns Promise resolving to stash commit SHA
*/
function stash(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
message?: string;
author?: PersonObject;
cache?: object;
}): Promise<string>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
// Stash current changes
const stashSha = await git.stash({
fs,
dir: "/path/to/repo",
message: "WIP: working on new feature",
author: {
name: "Developer",
email: "dev@example.com"
}
});
console.log("Created stash:", stashSha);Creates a packfile containing Git objects.
/**
* Pack Git objects into a packfile
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.oids - Object IDs to pack
* @param args.write - Write packfile to disk
* @returns Promise resolving to packfile info
*/
function packObjects(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
oids: string[];
write?: boolean;
}): Promise<PackObjectsResult>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
// Get commits to pack
const commits = await git.log({
fs,
dir: "/path/to/repo",
depth: 10
});
const oids = commits.map(commit => commit.oid);
// Create packfile
const packResult = await git.packObjects({
fs,
dir: "/path/to/repo",
oids,
write: true
});
console.log("Created packfile:", packResult.filename);Indexes a packfile for efficient access.
/**
* Index a packfile
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.filepath - Path to packfile
* @param args.cache - Cache object
* @returns Promise resolving when indexing completes
*/
function indexPack(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
filepath: string;
cache?: object;
}): Promise<void>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
// Index a packfile
await git.indexPack({
fs,
dir: "/path/to/repo",
filepath: "/path/to/packfile.pack"
});
console.log("Packfile indexed successfully");Adds a note to a Git object.
/**
* Add a note to an object
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.oid - Object ID to annotate
* @param args.note - Note content
* @param args.ref - Notes reference (defaults to 'refs/notes/commits')
* @param args.author - Author information
* @param args.committer - Committer information
* @param args.signingKey - PGP signing key
* @param args.force - Overwrite existing note
* @returns Promise resolving when note is added
*/
function addNote(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
oid: string;
note: string;
ref?: string;
author?: PersonObject;
committer?: PersonObject;
signingKey?: string;
force?: boolean;
}): Promise<void>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
// Add note to a commit
await git.addNote({
fs,
dir: "/path/to/repo",
oid: "commit-sha-here",
note: "This commit fixes issue #123",
author: {
name: "Annotator",
email: "annotator@example.com"
}
});Lists all notes in the repository.
/**
* List notes
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.ref - Notes reference (defaults to 'refs/notes/commits')
* @returns Promise resolving to array of note entries
*/
function listNotes(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
ref?: string;
}): Promise<NoteEntry[]>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
const notes = await git.listNotes({
fs,
dir: "/path/to/repo"
});
for (const note of notes) {
console.log(`Note for ${note.target}: ${note.note}`);
}Reads a note for a specific object.
/**
* Read a note for an object
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.oid - Object ID to read note for
* @param args.ref - Notes reference (defaults to 'refs/notes/commits')
* @returns Promise resolving to note content
*/
function readNote(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
oid: string;
ref?: string;
}): Promise<string>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
try {
const note = await git.readNote({
fs,
dir: "/path/to/repo",
oid: "commit-sha-here"
});
console.log("Note:", note);
} catch (err) {
console.log("No note found for this commit");
}Removes a note from an object.
/**
* Remove a note from an object
* @param args.fs - File system client
* @param args.dir - Working tree directory path
* @param args.gitdir - Git directory path
* @param args.oid - Object ID to remove note from
* @param args.ref - Notes reference (defaults to 'refs/notes/commits')
* @param args.author - Author information
* @param args.committer - Committer information
* @param args.signingKey - PGP signing key
* @returns Promise resolving when note is removed
*/
function removeNote(args: {
fs: FsClient;
dir?: string;
gitdir?: string;
oid: string;
ref?: string;
author?: PersonObject;
committer?: PersonObject;
signingKey?: string;
}): Promise<void>;Usage Example:
import git from "isomorphic-git";
import fs from "fs";
// Remove note from commit
await git.removeNote({
fs,
dir: "/path/to/repo",
oid: "commit-sha-here",
author: {
name: "Editor",
email: "editor@example.com"
}
});interface MergeResult {
oid?: string;
alreadyMerged?: boolean;
fastForward?: boolean;
mergeCommit?: boolean;
tree?: string;
conflicts?: string[];
}
interface WalkerEntry {
type: () => Promise<string>;
mode: () => Promise<string>;
oid: () => Promise<string>;
content: () => Promise<Uint8Array>;
stat: () => Promise<Stats>;
}
interface Walker {
(args: any): WalkerEntry;
}
interface PackObjectsResult {
filename: string;
packfile: Uint8Array;
}
interface NoteEntry {
target: string;
note: string;
}
// Walker constants
const STAGE: Walker; // Git index walker
const TREE: Walker; // Git tree walker
const WORKDIR: Walker; // Working directory walkerimport git from "isomorphic-git";
import fs from "fs";
try {
// Attempt merge
const result = await git.merge({
fs,
dir: "/path/to/repo",
theirs: "feature-branch"
});
if (result.conflicts && result.conflicts.length > 0) {
console.log("Merge conflicts in:", result.conflicts);
// Manual conflict resolution would happen here
// After resolving conflicts, commit the merge:
await git.add({ fs, dir: "/path/to/repo", filepath: "conflicted-file.js" });
await git.commit({
fs,
dir: "/path/to/repo",
message: "Resolve merge conflicts",
author: { name: "Developer", email: "dev@example.com" }
});
}
} catch (error) {
// If merge fails, abort it
await git.abortMerge({ fs, dir: "/path/to/repo" });
console.log("Merge aborted due to error:", error.message);
}import git, { TREE, WORKDIR } from "isomorphic-git";
import fs from "fs";
// Analyze repository changes
const analysis = await git.walk({
fs,
dir: "/path/to/repo",
trees: [TREE({ ref: "HEAD" }), WORKDIR()],
map: async (filepath, [head, workdir]) => {
if (!filepath.endsWith('.js')) return null;
if (head && workdir) {
const headContent = await head.content();
const workdirContent = await workdir.content();
if (!headContent.equals(workdirContent)) {
return {
filepath,
status: "modified",
headSize: headContent.length,
workdirSize: workdirContent.length
};
}
}
return null;
}
});
const jsChanges = analysis.filter(a => a !== null);
console.log("Modified JavaScript files:", jsChanges);