Skip to content

keydown-app/ts-git

Repository files navigation

TS-Git Logo

TS-Git

Local-only TypeScript Git implementation with pluggable filesystem support

Alpha License: MIT TypeScript

⚠️ Warning: This project is in early alpha. APIs may change, and not all Git features are implemented yet.


About

TS-Git is a pure TypeScript implementation of Git that runs entirely in the browser or Node.js environment. It provides a Git-compatible API with pluggable filesystem adapters, allowing you to work with Git repositories using various storage backends.

Key Features

  • πŸ”§ Pluggable Filesystem - Works with in-memory, browser storage, or native filesystems
  • πŸ“¦ Zero Dependencies - Lightweight implementation with minimal external dependencies
  • πŸ§ͺ Well Tested - Comprehensive test suite with 470+ tests
  • 🌐 Browser Native - Run Git operations directly in the browser
  • πŸ’ͺ Type Safe - Fully typed with TypeScript

Installation

npm install @keydown-app/ts-git

The package also exports an optional embedded terminal command surface as @keydown-app/ts-git/cli (CommandParser, prompts overridable via CommandContext.copy).

Quick Start

import { GitClient, MemoryFSAdapter } from '@keydown-app/ts-git';

// Create a filesystem adapter (in-memory for this example)
const fs = new MemoryFSAdapter();

// Initialize Git client
const git = new GitClient({ fs, dir: '/my-repo' });

// Initialize a repository
await git.init({ defaultBranch: 'main' });

// Stage and commit files
await git.add('README.md');
await git.commit('Initial commit', {
  name: 'John Doe',
  email: 'john@example.com',
});

// View commit history
const commits = await git.log();

Supported Git Commands

Command Status Description
init βœ… Supported Initialize a new Git repository
add <file> βœ… Supported Stage file(s) for commit
add -A βœ… Supported Stage all changes
rm <file> βœ… Supported Remove file(s) from index
commit -m βœ… Supported Create a new commit
status βœ… Supported Show working tree status
log βœ… Supported Show commit history
branch βœ… Supported List branches
branch <name> βœ… Supported Create new branch
branch -d/-D βœ… Supported Delete branch
checkout <branch> βœ… Supported Switch branches
reset [file] βœ… Supported Unstage file(s)
diff βœ… Supported Show changes between commits/index/worktree
diff --cached βœ… Supported Show staged changes (index vs HEAD)
diff --name-only βœ… Supported Show only names of changed files
diff --name-status βœ… Supported Show names and status of changed files
diff --stat βœ… Supported Show diffstat summary

Plumbing Commands (Low-Level API)

These commands provide direct access to Git's underlying object model. They are useful for building advanced tools or implementing custom version control workflows.

Command Status Description
cat-file βœ… Supported Read object content by OID
cat-file -t βœ… Supported Show object type
cat-file -p βœ… Supported Pretty-print object content
hash-object βœ… Supported Hash content and return OID
hash-object -w βœ… Supported Hash and write to object store
ls-tree βœ… Supported List tree entries by OID or ref
ls-tree -r βœ… Supported Recursive tree listing
update-index βœ… Supported Manually update index entries
update-index --add βœ… Supported Stage file to index
update-index --remove βœ… Supported Unstage file from index

| tag | ❌ Not Supported | Create, list, or delete tags | | merge | ❌ Not Supported | Join development histories | | rebase | ❌ Not Supported | Reapply commits on top of another base | | cherry-pick | ❌ Not Supported | Apply changes from specific commits | | stash | ❌ Not Supported | Stash changes | | clone | ❌ Not Supported | Clone a repository | | fetch | ❌ Not Supported | Download objects from remote | | pull | ❌ Not Supported | Fetch and merge | | push | ❌ Not Supported | Update remote refs | | remote | ❌ Not Supported | Manage tracked repositories | | config | ❌ Not Supported | Get/set repository options | | show | ❌ Not Supported | Show various types of objects |

Examples

Web UI Example

Run the interactive web-based Git terminal:

npm run dev

This starts a development server with a terminal interface for testing Git commands.

With Tauri (Desktop App)

npm run dev:tauri

With ZenFS (Browser Filesystem)

npm run dev:zen

Filesystem Adapters

TS-Git supports multiple filesystem adapters:

  • MemoryFSAdapter - In-memory storage (great for testing)
  • TauriFSAdapter - Native filesystem via Tauri
  • ZenFSAdapter - Browser-based persistent storage
  • FileSystemAccessAdapter - Native File System Access API
  • CustomFSAdapter - Create your own custom filesystem adapter

To create your own filesystem adapter, you can extend the FSAdapter interface and implement the methods. See the examples for more details.

Development

# Install dependencies
pnpm install

# Build all packages
npm run build

# Run tests
npm test

# Type check
npm run typecheck

# Lint
npm run lint

# Format code
npm run format

Project Structure

ts-git/
β”œβ”€β”€ packages/
β”‚   └── ts-git/          # Core Git implementation
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ commands/  # Git command implementations
β”‚       β”‚   β”œβ”€β”€ core/      # Core Git objects (blob, tree, commit)
β”‚       β”‚   β”œβ”€β”€ client/    # GitClient wrapper class
β”‚       β”‚   β”œβ”€β”€ cli/       # Optional CommandParser (embedded terminal)
β”‚       β”‚   └── fs/        # Filesystem adapters
β”‚       └── package.json
β”‚   └── ts-git-ui/         # Web UI example
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ components/ # Web UI components
β”‚       β”‚   β”œβ”€β”€ styles.css # Web UI styles
β”‚       β”‚   └── package.json
β”‚   └── ts-git-diff-myers/ # Myers line diff implementation
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ myers.ts
β”‚       β”‚   └── package.json
β”‚   └── ts-git-diff-words/ # Prose/word diff implementation (placeholder)
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ word.ts
β”‚       β”‚   └── package.json
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ with-memory-fs/   # In-memory filesystem example
β”‚   β”œβ”€β”€ with-tauri-fs/    # Desktop app example
β”‚   └── with-zen-fs/      # Browser filesystem example
└── package.json

Contributing

Contributions are welcome! This project is in early alpha, so please expect API changes as we stabilize the codebase.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Diff Command Implementation

The diff command is now implemented with the following capabilities:

Supported Features

  • Worktree vs Index (git diff): Shows unstaged changes in tracked files
  • Index vs HEAD (git diff --cached or --staged): Shows staged changes
  • Commit comparisons (git diff A B): Shows differences between two commits
  • Path filtering (git diff -- <path>): Limits diff to specific paths
  • Output formats:
    • Default unified diff with patch format
    • --name-only: Lists only changed filenames
    • --name-status: Shows status (A/M/D) and filenames
    • --stat: Shows diffstat summary

Known Limitations

Index and status

  • Index version 4 is rejected; use Git index version 2 or 3 (e.g. git config core.indexVersion 3 and re-index).
  • Unmerged (multi-stage) index entries are collapsed to a single representative stage for status and diff (not full UU / conflict semantics).
  • assume-unchanged / skip-worktree flags are parsed from CLI-produced indices but behavior may not match Git’s status rules in all cases.

The following git diff features are not yet implemented:

  • Rename detection (-M, -C, --find-renames, --find-copies): Files moved or copied appear as separate deletions and additions
  • Merge-base diffs (--merge-base, A...B syntax): Triple-dot notation treats both sides as regular commits
  • Binary file handling: Binary files are detected but content diffing is not fully supported
  • No-index mode (--no-index): Comparing paths outside a git repository
  • Range notation (A^!, A^@): Special revision range syntaxes
  • Word diff (--word-diff): Word-level diffs instead of line-level
  • Color output: ANSI color codes in diff output
  • Config-driven defaults: Respecting diff.* configuration options

Output Compatibility

The unified diff output format follows Git's standard conventions:

  • diff --git a/<path> b/<path> headers
  • index <oid>..<oid> lines for modified files
  • new file mode / deleted file mode indicators
  • --- a/<path> / +++ b/<path> markers (with /dev/null for add/delete)
  • Unified hunk headers with @@ -l,s +l,s @@
  • Context lines prefixed with space, additions with +, deletions with -

Minor formatting differences from canonical Git output may exist in edge cases.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A local subset of Git commands for in TypeScript designed to enable version control with TS file systems.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors