This guide walks you through the low-level construction of a Git commit using the @git-stunts/plumbing high-level domain entities and services.
The foundation of every Git repository is the blob (binary large object). Blobs store file content without filenames or metadata.
import { GitBlob } from '@git-stunts/plumbing';
// Create a blob from string content
const blob = GitBlob.fromContent('Hello, Git Plumbing!');
// Or from a Uint8Array
const binaryBlob = GitBlob.fromContent(new Uint8Array([1, 2, 3]));Trees map filenames to blobs (or other trees) and assign file modes.
import { GitTree, GitTreeEntry, GitSha } from '@git-stunts/plumbing';
// Define entries
const entry = new GitTreeEntry({
path: 'hello.txt',
sha: GitSha.from('...'), // The SHA returned from persisting the blob
mode: '100644'
});
// Create the tree
const tree = new GitTree(null, [entry]);Commits wrap trees with metadata like author, committer, and message.
import { GitCommit, GitSignature, GitSha } from '@git-stunts/plumbing';
const author = new GitSignature({
name: 'James Ross',
email: 'james@flyingrobots.dev'
});
const commit = new GitCommit({
sha: null,
treeSha: GitSha.from('...'), // The SHA returned from persisting the tree
parents: [], // Empty for root commit
author,
committer: author,
message: 'Feat: my first plumbing commit'
});Use the GitPersistenceService to write these objects to the Git object database.
import GitPlumbing, { GitPersistenceService } from '@git-stunts/plumbing';
const git = GitPlumbing.createDefault();
const persistence = new GitPersistenceService({ plumbing: git });
// Save objects
const blobSha = await persistence.writeBlob(blob);
const treeSha = await persistence.writeTree(tree);
const commitSha = await persistence.writeCommit(commit);Finally, point a branch to your new commit.
const repo = GitPlumbing.createRepository();
await repo.updateRef({
ref: 'refs/heads/main',
newSha: commitSha
});