A pure Dart implementation of Git, optimized for Flutter mobile applications (Android & iOS). Build native Git clients for mobile with full local and remote repository support.
- β
Repository Management:
init,open - β
Staging:
add,status - β
Commits:
commit,log - β Branching: create, delete, list branches
- β Checkout: switch branches and restore files
- β Merging: 3-way merge with conflict detection
- β Rebasing: interactive rebase support
- β Remote Management: add, remove, list remotes
- β Clone: create local copy of remote repository
- β Fetch: download refs and objects from remote
- β Push: upload commits to remote (with force option)
- β Pull: fetch and merge in one operation
- β Authentication: HTTPS (token, basic auth), SSH (key-based)
- π Git Protocol Compatible: Standard DIRC index format, SHA-1 hashing, tree objects
- π± Mobile Optimized: Memory-efficient streaming I/O, async/await throughout
- π Type Safe: Strong typing with comprehensive error handling via
GitResult<T> - β¨ Flutter Ready: Works seamlessly with Flutter for Android and iOS
- π Cross-Platform: Android, iOS, Linux, macOS, Windows
Add to your pubspec.yaml:
dependencies:
git_on_dart: ^0.1.0Then run:
dart pub getimport 'package:git_on_dart/git_on_dart.dart';
// Create a new repository
final repo = await GitRepository.init('/path/to/repo');
// Or open an existing one
final repo = await GitRepository.open('/path/to/repo');// Stage files
final addOp = AddOperation(repo);
await addOp.addFiles(['lib/main.dart', 'pubspec.yaml']);
// Check status
final statusOp = StatusOperation(repo);
final status = await statusOp.getStatus();
print('Modified: ${status.modified.length}');
print('Staged: ${status.staged.length}');
// Commit changes
final commitOp = CommitOperation(repo);
final author = GitAuthor(
name: 'Your Name',
email: 'your@email.com',
timestamp: DateTime.now(),
);
final result = await commitOp.commit(
message: 'Initial commit',
author: author,
);
print('Commit: ${result.data}');// Create and switch to a new branch
await repo.refManager.createBranch('feature-branch');
final checkoutOp = CheckoutOperation(repo);
await checkoutOp.checkout('feature-branch');
// Make changes and commit...
// Switch back and merge
await checkoutOp.checkout('main');
final mergeOp = MergeOperation(repo);
final mergeResult = await mergeOp.merge('feature-branch');
if (mergeResult.hasConflicts) {
print('Conflicts in: ${mergeResult.conflicts.keys}');
// Handle conflicts...
}// Clone a repository
final cloneOp = CloneOperation();
final cloneResult = await cloneOp.clone(
url: 'https://github.com/username/repo.git',
path: '/path/to/destination',
credentials: HttpsCredentials.token('your_token'),
);
if (cloneResult.success) {
print('Cloned to ${cloneResult.repository!.workDir}');
}
// Add a remote
final remoteManager = RemoteManager(repo);
await remoteManager.addRemote(
name: 'origin',
url: 'https://github.com/username/repo.git',
);
// Configure authentication
final credentials = HttpsCredentials.token('your_github_token');
// Push changes
final pushOp = PushOperation(repo);
final pushResult = await pushOp.push(
remoteName: 'origin',
refspec: 'main:main',
credentials: credentials,
);
// Pull changes
final pullOp = PullOperation(repo);
final pullResult = await pullOp.pull(
remoteName: 'origin',
branch: 'main',
credentials: credentials,
);// Using SSH keys (now fully supported!)
final sshCreds = SshCredentials(
privateKeyPath: '/path/to/id_rsa',
passphrase: 'optional_passphrase', // if key is encrypted
);
// Push via SSH
await pushOp.push(
remoteName: 'origin',
refspec: 'main:main',
credentials: sshCreds,
);
// Fetch via SSH
final fetchOp = FetchOperation(repo);
await fetchOp.fetch(
remoteName: 'origin',
credentials: sshCreds,
);
// Supported SSH URL formats:
// - git@github.com:user/repo.git
// - ssh://git@github.com/user/repo.gitAll operations return GitResult<T> for consistent error handling:
final result = await commitOp.commit(
message: 'My commit',
author: author,
);
if (result.isSuccess) {
print('Commit hash: ${result.data}');
} else {
print('Error: ${result.error?.message}');
print('Type: ${result.error?.type}');
}The package includes several comprehensive examples:
Complete working example demonstrating:
- Repository initialization
- File staging and commits
- Branch management
- Merge operations
- Status checking
SSH authentication examples:
- Fetch with SSH keys
- Push with SSH authentication
- Pull operations
Repository cloning scenarios:
- Clone public repositories
- Clone with HTTPS token auth
- Clone with SSH
- Progress tracking
- Bare repositories
- Custom branch and remote names
Run examples with:
dart run example/git_demo.dart
dart run example/ssh_example.dart
dart run example/clone_example.dart- Core: Repository management, object database, index, refs
- Models: Git objects (blob, tree, commit), authors, results
- Operations: Modular operations for each git command
- Remote: Remote repository management and network operations
For detailed implementation notes, see IMPLEMENTATION.md.
The package includes comprehensive test coverage:
dart test- 12 local operation tests
- 31 remote operation tests
- 6 clone operation tests
- Full workflow integration tests
- Pack Protocol: Simplified implementation for basic push/pull operations (full git pack protocol in progress)
- Large Files: Optimized for mobile apps; no LFS support yet
- Advanced Features: Stash, cherry-pick, interactive rebase, and submodules not yet implemented
- β Clone Operation: Full repository cloning with HTTPS and SSH
- β Progress tracking, bare repositories, branch selection
- β Automatic tracking branch configuration
- β New comprehensive clone examples
- β
Full SSH Support: Push and pull operations now work with SSH authentication via
dartssh2package - β
Supports both
git@host:pathandssh://user@host/pathURL formats - β SSH key-based authentication with optional passphrase support
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.