Edited by humans. Written by AI. How our editing works
All articles

How to Build Git Version Control Into Your Apps

LibGit2 lets developers embed Git functionality directly into applications. Here's what that actually looks like in practice, and why it matters.

Tyler Nakamura

Written by AI. Tyler Nakamura

April 11, 20266 min read
Share:
Dark blue presentation slide with cyan geometric lines displaying the title and speaker name Richard Thomson from Utah C++…

Photo: Utah Cpp Programmers / YouTube

Your app probably has configuration files. Maybe user settings, maybe JSON exports, maybe something custom. And if you're like most developers, you've probably thought: "wouldn't it be cool if users could undo changes to this?"

Turns out, you can just... build Git into your app. LibGit2 is the library that makes this possible, and developer Richard Thomson recently walked through exactly how to do it in a presentation for the Utah C++ Programmers group.

The demo app is dead simple—a text editor that tracks every save as a Git commit. Users can browse their edit history, jump back to previous versions, and restore old content. All the version control goodness of Git, but invisible to the user. No command line, no repository cloning, no merge conflicts to explain.

The Licensing Catch That Isn't Really a Catch

First thing you're probably wondering: can I actually use this commercially? LibGit2 is GPL2, which normally means "open source your entire app or don't touch this." But there's a linking exception that changes everything.

"As long as you don't modify libgit2 itself, you can link it into your application and you're not required to distribute the source code of your application," Thomson explains. "If you modify the library itself, you have to make your modifications available in source code form."

That's actually pretty reasonable. Use the library as-is, and your proprietary code stays proprietary. Fork the library to add features, and you contribute those features back. Most developers will never need to modify LibGit2 itself.

The Problem: LibGit2 Is Written in C

Here's where it gets interesting. LibGit2 is a C library, not C++. Everything's done with opaque pointers, handle types, and C-style functions. The official C++ binding exists, but it's coupled to Qt—which means if you're not already using Qt, you're dragging in a massive framework just to get some C++ syntax sugar.

Thomson's approach: write your own lightweight wrappers. Just the parts you need, nothing more.

His demo app needs exactly five things from the version control system:

  • Get a configuration string from the repository
  • Commit files
  • Get the history of a file
  • Get the content of a file
  • Check if the repository is empty

That's it. Git has hundreds of operations available. Thomson's application facade exposes five methods.

The Simplifying Facade Pattern

This is the clever part. Instead of wrapping LibGit2's entire API surface, Thomson created an abstract interface that only exposes what his app actually needs. The implementation uses LibGit2, but the app never touches LibGit2 directly.

"I'm not writing a git /article/why-devs-are-ditching-github-for-self-hosted-git client in the sense of like you would interact from the command line when you're managing the source control versions of your source code," he says. "I am just controlling the needs of my application here."

The benefits stack up fast:

  • Your app code stays clean and simple
  • You can mock the interface for unit testing
  • You could theoretically swap Git for Mercurial or another VCS without touching app code
  • You don't accidentally use Git features you don't understand

It's the classic software architecture move: add a layer of indirection that constrains what you can do, which paradoxically makes everything easier.

Handling the C API Without Losing Your Mind

C APIs return error codes, not exceptions. C APIs use opaque pointers that you have to manually free. C APIs require library initialization before you can call anything.

Thomson's wrapper types solve all of this:

  1. Every wrapper holds a lifetime member that ensures LibGit2 stays initialized as long as the wrapper exists
  2. Destructors automatically free the opaque handles
  3. A simple error-checking function converts LibGit2's error codes into C++ exceptions
  4. The wrappers are non-copyable and non-movable—you can't accidentally double-free a handle

The wrappers ended up covering about a dozen LibGit2 types: repository, index, tree, signature, object ID, commit, revision walker, blob, config, diff, and tree entry. Each one is just enough wrapper to make the C API feel like C++.

The Copilot Shortcut

Here's a detail that matters: Thomson used GitHub Copilot to help write these wrappers. He'd write the first wrapper by hand, then let Copilot generate the rest following the same pattern.

"I'd already extracted a wrapper by hand for the repository. So when it was extracting new wrappers, it was just following my examples," he notes. "I didn't have to get specific about things like, you know, they're not copy constructable, they're not move constructible."

This is actually how AI coding tools should work—you establish the pattern, the tool handles the repetitive parts while maintaining consistency.

What This Actually Enables

The demo shows version control for a single text file, but the pattern scales to way more interesting use cases:

  • Configuration files that users can revert when they break something
  • Auto-saving drafts with full undo history beyond simple undo/redo
  • Application state that can be rolled back to any previous point
  • Settings that track who changed what and when in multi-user environments
  • Automatic backups that don't duplicate unchanged data

All without users knowing what Git is. The repository lives in the standard user data directory for your app. The GUI shows "version history" instead of "commits." Users click "restore previous version" instead of running git checkout.

The Part Nobody Mentions

What's missing from most LibGit2 tutorials is the messy middle—how do you actually decide which parts of the API to wrap? Thomson's answer is pragmatic: let your use case drive it. Start with the abstract interface your app needs. Implement just enough wrapper to support that interface. Add more wrappers only when you need them.

"The reason I recommend doing this is because it keeps you from getting seduced into creating elaborate sets of APIs around the entire functionality of Git that you'll never use," he explains. "So, it's just wasted effort, right?"

The full source code is on GitHub. The approach works. And it raises a question worth sitting with: how many other "power user" tools could we embed invisibly into apps, making advanced features accessible to people who'd never touch a terminal?

—Tyler Nakamura

From the BuzzRAG Team

We Watch Tech YouTube So You Don't Have To

Get the week's best tech insights, summarized and delivered to your inbox. No fluff, no spam.

Weekly digestNo spamUnsubscribe anytime

More Like This

Yellow arrow pointing to a broken red Git logo icon on black background with "GIT FIX?" text above

GitButler Rethinks Git Workflow With Virtual Branches

GitButler from GitHub co-founder adds virtual branches and AI commits to Git. Better Stack tests whether it solves Git's context-switching pain points.

Rachel "Rach" Kovacs·5 months ago·5 min read
A shocked man with wide eyes appears next to the Linear logo and text reading "Issue tracking is dead" against a dark…

Linear Says Issue Tracking Is Dead. Here's What's Next

Linear, the issue tracker beloved by engineers, just declared its own category obsolete. AI agents are changing how software gets built—for better or worse.

Tyler Nakamura·4 months ago·6 min read
Woman in thoughtful pose next to three boxes labeled with X and checkmarks, illustrating branching strategies comparison on…

Navigating Git Workflows: Which One Fits Your Team?

Explore GitFlow, GitHub Flow, and Trunk-Based Development to find the best workflow for your team.

Tyler Nakamura·6 months ago·3 min read
Three developers at computers with code on screens, illuminated by orange and blue lighting in a tech workspace environment

Explore GitHub's Hottest Open-Source Projects

Dive into GitHub's top trending projects this week, from AI tools to web enhancements.

Tyler Nakamura·6 months ago·3 min read
Speaker at podium discussing C++ pathfinding issues with circuit board graphics and green network visualization on dark…

Age of Empires' 25-Year Pathfinding Bug Had a Wild Cause

How a compiler flag change accidentally broke Age of Empires pathfinding for years—and why the community was right all along about the units walking through walls.

Tyler Nakamura·5 months ago·6 min read
Man wearing headphones with shocked expression between glowing ChatGPT and GitHub logos surrounded by flames

Why OpenAI Might Build Its Own GitHub Alternative

OpenAI is reportedly developing an internal alternative to GitHub. The move signals a larger shift in how version control works in an AI-driven world.

Bob Reynolds·4 months ago·6 min read
Man in beanie holding AI compute invoice totaling $287.43, with "Beat 20 People" text overlay on black background

The Karpathy Loop: When AI Runs 700 Experiments Overnight

Andre Karpathy's AI agent ran 700 experiments while he slept, found bugs he missed, and cut training time 11%. Here's what that means for everyone else.

Tyler Nakamura·3 months ago·7 min read
Man wearing glasses with skeptical expression beside text "TOO GOOD TO RELEASE?" against black background with decorative…

Anthropic's Claude Mythos Found Thousands of Zero-Days

Anthropic's new Claude Mythos AI discovered thousands of zero-day vulnerabilities, prompting a defensive security initiative before public release.

Tyler Nakamura·3 months ago·6 min read

RAG·vector embedding

2026-04-15
1,322 tokens1536-dimmodel text-embedding-3-small

This article is indexed as a 1536-dimensional vector for semantic retrieval. Crawlers that parse structured data can use the embedded payload below.