Recently I’ve been exploring using “files in a Git repository” as the main storage for iOS and Mac apps. I’ve got two little projects using this.
The key technology that enables this approach is libgit2, which is a C language implementation of the core git methods.
There are at least two popular ways to use libgit2
from iOS / Mac.
The first, ObjectiveGit, is Objective-C bindings to the C API.
The second, SwiftGit2, is a set of Swift bindings.
Being me, I wound up going with neither of these libraries. Things that made me shy away:
- Neither project use Swift Package Manager, which I use exclusively in my personal projects.
- Neither project has been updated recently. SwiftGit2 links against version 1.1 of libgit2 (the library is now, at the time of this writing, at version 1.5). ObjectiveGit is worse, linking against version 0.28.1!
So I’ve approached git integration to Swift iOS/Mac apps from first principles and created two projects:
-
static-libgit2
is a Swift package that exposes thelibgit2
C API through theClibgit2
module. This project is a modification ofLibGit2-On-iOS
and follows the same basic strategy:- Use build scripts to build
libgit2
and its dependencies (libssh
,openssl
) and create a singlexcframework
for all of the necessary SDK and architecture variations. - Create a
Package.swift
file to let projects include thexcframework
through Swift Package Manager.
static-libgit2
is pretty stable, and if you want to just use the C APIs in a Swift app, it gives you want you want. It’s ready for public consumption now.import Clibgit2 import SwiftUI struct ContentView: View { var body: some View { Text(LIBGIT2_VERSION) .padding() } }
- Use build scripts to build
-
AsyncSwiftGit
is much more experimental and much less stable. It’s my attempt to write Swift wrappers around the C API that uses the new concurrency features of Swift 5.5. For example, instead of passing in C-compatible callback functions when fetching changes from a remote repository, I can write:for try await progress in repository.fetchProgressStream(remote: "origin", credentials: credentials) { // do something with `progress` here }
This is “more experimental and less stable” because I’m still figuring out the right way to use Swift concurrency, the best way to design wrappers around a C API, etc. This one is not yet ready for public consumption.
Overall, though, I’ve been really impressed with how fun and reliable it is to use git as the main storage system for personal programming projects! I predict I’ll be using it more and more.