Skip to main content
wit provides classes for working with Git objects directly. This is useful for building tools, analyzing repositories, or understanding Git internals.

Object Types

TypeClassDescription
blobBlobFile content
treeTreeDirectory structure
commitCommitRepository snapshot
tagTagAnnotated tag

Blob

A blob stores file content.
import { Blob } from 'wit/core';

// Create a blob
const blob = new Blob(Buffer.from('Hello, world!'));

// Get content
console.log(blob.content.toString()); // "Hello, world!"

// Serialize for storage
const data = blob.serialize();

Properties

PropertyTypeDescription
type'blob'Object type
contentBufferRaw file content

Methods

MethodReturnsDescription
serialize()BufferSerialize for storage
toString()stringContent as UTF-8 string

Tree

A tree represents a directory, containing references to blobs (files) and other trees (subdirectories).
import { Tree, TreeEntry } from 'wit/core';

// Create a tree
const entries: TreeEntry[] = [
  { mode: '100644', name: 'README.md', hash: 'abc123...' },
  { mode: '100755', name: 'script.sh', hash: 'def456...' },
  { mode: '40000', name: 'src', hash: '789abc...' },
];

const tree = new Tree(entries);

// Access entries
for (const entry of tree.entries) {
  console.log(`${entry.mode} ${entry.name} ${entry.hash}`);
}

// Serialize (entries are automatically sorted)
const data = tree.serialize();

TreeEntry

interface TreeEntry {
  mode: string;   // File mode
  name: string;   // File/directory name
  hash: string;   // Object hash (blob or tree)
}

File Modes

ModeDescription
100644Regular file
100755Executable file
120000Symbolic link
40000Directory (tree)
160000Submodule (commit)

Methods

MethodReturnsDescription
serialize()BufferSerialize for storage
static deserialize(data)TreeParse from buffer

Commit

A commit represents a snapshot of the repository.
import { Commit, Author } from 'wit/core';

const author: Author = {
  name: 'Alice',
  email: 'alice@example.com',
  timestamp: Math.floor(Date.now() / 1000),
  timezone: '-0800',
};

const commit = new Commit({
  tree: 'abc123...',           // Tree hash
  parents: ['def456...'],      // Parent commit hashes
  author,
  committer: author,
  message: 'Add new feature',
});

// Access properties
console.log(commit.tree);      // Tree hash
console.log(commit.parents);   // Parent hashes
console.log(commit.message);   // Commit message

// Serialize
const data = commit.serialize();

Properties

PropertyTypeDescription
type'commit'Object type
treestringTree object hash
parentsstring[]Parent commit hashes
authorAuthorWho wrote the changes
committerAuthorWho created the commit
messagestringCommit message

Author

interface Author {
  name: string;      // Display name
  email: string;     // Email address
  timestamp: number; // Unix timestamp
  timezone: string;  // Timezone offset (e.g., "-0800")
}

Methods

MethodReturnsDescription
serialize()BufferSerialize for storage
static deserialize(data)CommitParse from buffer

Tag

An annotated tag with message and tagger info.
import { Tag, Author } from 'wit/core';

const tagger: Author = {
  name: 'Bob',
  email: 'bob@example.com',
  timestamp: Math.floor(Date.now() / 1000),
  timezone: '+0000',
};

const tag = new Tag({
  object: 'abc123...',   // Tagged object hash
  type: 'commit',        // Tagged object type
  name: 'v1.0.0',        // Tag name
  tagger,
  message: 'Release version 1.0.0',
});

// Access properties
console.log(tag.name);     // "v1.0.0"
console.log(tag.message);  // "Release version 1.0.0"

Properties

PropertyTypeDescription
type'tag'Object type
objectstringTagged object hash
objectTypestringTagged object type
namestringTag name
taggerAuthorWho created the tag
messagestringTag message

Object Store

The ObjectStore class handles reading and writing objects.
import { Repository } from 'wit/core';

const repo = Repository.open('.');

// Write a blob
const blob = new Blob(Buffer.from('content'));
const hash = repo.objects.writeObject(blob);
console.log(`Stored as: ${hash}`);

// Read an object
const obj = repo.objects.readObject(hash);
console.log(obj.type);  // 'blob'

// Write raw content as blob
const blobHash = repo.objects.writeBlob(Buffer.from('content'));

// Check if object exists
if (repo.objects.hasObject(hash)) {
  console.log('Object exists');
}

// Read raw object data
const { type, content } = repo.objects.readRawObject(hash);

Methods

MethodReturnsDescription
writeObject(obj)stringWrite object, return hash
readObject(hash)GitObjectRead and parse object
writeBlob(content)stringWrite content as blob
hasObject(hash)booleanCheck if object exists
readRawObject(hash){type, content}Read without parsing
readBlob(hash)BlobRead as blob
readTree(hash)TreeRead as tree
readCommit(hash)CommitRead as commit

Hashing

wit supports SHA-1 (Git compatible) and SHA-256 (more secure).
import { hashObject, setHashAlgorithm, getHashAlgorithm } from 'wit/core';

// Check current algorithm
console.log(getHashAlgorithm());  // 'sha1' or 'sha256'

// Set algorithm (usually done at repo init)
setHashAlgorithm('sha256');

// Hash an object
const hash = hashObject('blob', Buffer.from('content'));
console.log(hash);  // 64-char hex string for SHA-256

Examples

Walk a Tree

function walkTree(repo: Repository, treeHash: string, prefix = '') {
  const tree = repo.objects.readTree(treeHash);
  
  for (const entry of tree.entries) {
    const path = prefix ? `${prefix}/${entry.name}` : entry.name;
    
    if (entry.mode === '40000') {
      // Directory - recurse
      console.log(`📁 ${path}/`);
      walkTree(repo, entry.hash, path);
    } else {
      // File
      console.log(`📄 ${path}`);
    }
  }
}

const repo = Repository.open('.');
const head = repo.refs.resolve('HEAD');
const commit = repo.objects.readCommit(head);
walkTree(repo, commit.tree);

Find All Blobs in a Commit

function findBlobs(repo: Repository, commitHash: string): string[] {
  const blobs: string[] = [];
  const commit = repo.objects.readCommit(commitHash);
  
  function walkTree(treeHash: string) {
    const tree = repo.objects.readTree(treeHash);
    for (const entry of tree.entries) {
      if (entry.mode === '40000') {
        walkTree(entry.hash);
      } else {
        blobs.push(entry.hash);
      }
    }
  }
  
  walkTree(commit.tree);
  return blobs;
}

Create a Commit Programmatically

import { Repository, Blob, Tree, Commit } from 'wit/core';

const repo = Repository.open('.');

// Create a blob
const blob = new Blob(Buffer.from('Hello, world!'));
const blobHash = repo.objects.writeObject(blob);

// Create a tree with the blob
const tree = new Tree([
  { mode: '100644', name: 'hello.txt', hash: blobHash },
]);
const treeHash = repo.objects.writeObject(tree);

// Create a commit
const commit = new Commit({
  tree: treeHash,
  parents: [], // No parents for initial commit
  author: {
    name: 'Bot',
    email: 'bot@example.com',
    timestamp: Math.floor(Date.now() / 1000),
    timezone: '+0000',
  },
  committer: {
    name: 'Bot',
    email: 'bot@example.com',
    timestamp: Math.floor(Date.now() / 1000),
    timezone: '+0000',
  },
  message: 'Initial commit',
});

const commitHash = repo.objects.writeObject(commit);
console.log(`Created commit: ${commitHash}`);

// Update HEAD
repo.refs.update('refs/heads/main', commitHash);