Async-first Git
for Swift
A modern, type-safe libgit2 wrapper. Branches, commits, diffs, merge, rebase, stash — all with a clean Swift API.
dependencies: [
.package(url: "https://github.com/RonenMars/Gitty", from: "0.1.0"),
]Everything Git, in Swift
Async-first
Clone, fetch, and push with native Swift concurrency. Synchronous operations stay fast and simple.
Zero dependencies
Bundles libgit2 as a pure SPM package. No Homebrew, no CMake, no system setup required.
Type-safe errors
All libgit2 error codes surface as GittyError. No silent failures, no raw integer codes.
Full branch & remote support
Create, delete, rename, checkout. Manage multiple remotes, fetch, and push with credentials.
Merge, Rebase & Cherry-pick
Typed merge results — up-to-date, fast-forward, merged, or conflict. Full rebase and cherry-pick support.
Diff & Blame
Typed hunks and lines from any diff. Blame any file to trace changes back to their original commit.
Tags & Stash
Lightweight and annotated tags. Full stash push, pop, apply, drop, and list.
Worktrees
Add, remove, lock, and unlock linked working trees for parallel branch workflows.
Flexible credentials
Token, username/password, SSH agent, or system credential helper — all supported out of the box.
A taste of the API
import Gitty
// Clone a private repo
let repo = try await Repository.clone(
from: URL(string: "https://github.com/user/repo")!,
to: localURL,
credentials: .token("ghp_yourtoken")
)
// Stage all changes and commit
let author = Signature(name: "Alice", email: "alice@example.com")
try repo.stageAll()
let commit = try repo.commit(message: "feat: add login", author: author)
// Merge a branch and handle the result
switch try repo.merge(branch: branch) {
case .fastForward(let c): print("Fast-forwarded to", c.oid.shortString)
case .merged(let c): print("Merged:", c.oid.shortString)
case .conflict(let files): print("Conflicts:", files.map(.path))
default: break
} Start building with Gitty
Add it to your Swift project in seconds. No system setup required.