libgit2: Git as a C library, and the licence question its licence field cannot answer
A cross-platform, linkable library implementation of Git that you can use in your application.
At a glance
- What is it?
- A pure C implementation of Git's core, used by forges, GUI clients and bindings in six languages, shipping two maintenance branches and a naming exception.
- Who is it for?
- libgit2 solves a specific problem that shelling out to git does not: putting Git inside a process that needs object-level access without spawning a subprocess per operation. For a forge, a GUI client or a tool that reads history as structured data, that is a capability you cannot get any other way in a language with a good binding.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Git's core methods, reimplemented rather than wrapped
The README's description is precise: libgit2 is a portable, pure C implementation of the Git core methods, provided as a linkable library with a solid API, so that Git functionality can be built into your application. Every word of that matters. It is not a binding to the git binary, it is not a reimplementation of the whole tool including its porcelain, and it is not a partial library that covers the easy cases.
That last exclusion is stated in the README's own capabilities section, which lists what the library provides: SHA conversions, formatting and shortening, an abstracted ODB backend system, and commit, tag, tree and blob parsing, editing and writing. Then it says that implementing Git the way Git implements it is out of scope for this library. So plumbing is in, and porcelain is not. If you need the behaviour of rebase, merge strategies or the index exactly as git produces it, you still want the binary.
The ODB backend abstraction is the piece that makes this more than a convenience. Because object storage is behind an interface rather than hardcoded to loose files or a packfile, an application can supply its own storage. That is how hosting providers put Git objects in a database or an object store instead of on a filesystem, and it is the reason libgit2 appears inside forges at all.
The README also says the library is used in a variety of places, from GUI clients to hosting providers and countless utilities in between. That is a credibility claim worth taking seriously: if a hosting provider and a desktop client both ship it, the API has been exercised against very different workloads.
The licence, and why GitHub shows you no badge
This project presents a licence situation that the repository metadata cannot express, and getting it right matters more here than for almost any other dependency. GitHub reports the licence field for this repository as NOASSERTION, meaning it detected something and could not classify it. The README explains the actual terms: libgit2 is licensed under a very permissive licence, GPLv2 with a special Linking Exception, which means you can link against the library with any kind of software without making that software fall under the GPL. Changes to libgit2 itself remain under the GPL.
So the two facts are not in conflict, they are one fact each describing a different half of it. The exception is what makes the arrangement usable, and the metadata field is blank because no standard licence name fits a GPL with a linking exception. The practical reading is that a proprietary application may link against libgit2 and remain closed, while a fork of libgit2 must respect the GPL. That is the arrangement you would expect from a library designed to be embedded in commercial products.
The `COPYING` file at the repository root holds the licence text, and if you are shipping this in a commercial product that is the file to read rather than either the README summary or the badge. The README's phrasing, very permissive, undersells the complexity of what it then describes, which is a small reason to read the actual text.
Given a project this old and this embedded, the version you adopt matters more than usual. The README's build matrix shows maintenance branches for v1.9 and v1.8 alongside main, and the releases list shows parallel patch releases on both lines published on the same day in August 2026, which is a maintainer supporting two supported series deliberately.
Bindings in six languages, and which one you probably want
The README's argument for a C library is reach, and it lists the bindings by name: Ruby through rugged, .NET through libgit2sharp, Python through pygit2, Node.js through nodegit, Rust through git2-rs, and more. The advice it gives is direct. If you are not writing in C, use a binding, because the binding exists to take care of the messy tasks of calling into native code.
That is the correct order of operations and it is worth following. Writing a native interface layer yourself means handling object lifetimes, converting between the library's handle types and your language's types, and getting threading right, none of which is where your product value is. The binding packages handle the parts of the API that are pleasant in C and unpleasant everywhere else.
Which binding to choose follows from your language rather than from anything about libgit2. The one thing worth checking per binding is its libgit2 version compatibility, since libgit2 ships breaking API changes between minor versions and a binding pinned to an older one will not track main. The releases list gives a good sense of the cadence: 1.9.6 in July 2026, then 1.8.7 and 1.9.7 together in August 2026, the latter a security release escaping repository paths in the libssh2 transport to avoid command injection.
That CVE is worth pausing on, because it explains a design decision rather than just being a bug fix. Escaping had been applied to the OpenSSH-based exec transport since 1.8.5, and this release brings the same escaping to the libssh2 transport. Two SSH transports meant two places to get escaping right, and one of them was wrong until a third party identified the issue. If you link libgit2 and use SSH remotes, this is the release line to be on.
Building it, and what the tree says about the project's priorities
The README says outright that libgit2 is not hard to compile, and the build is three commands. The prerequisites are CMake on your PATH, Python for the test framework, and a C compiler, with Visual Studio recommended on Windows, Xcode on Mac, and gcc or clang on Unix.
mkdir build && cd build
cmake ..
cmake --build .The package.json carries the same three steps in one string as its install hook, which is a nice detail for a project that is not a JavaScript package. It is there because the tree includes tooling that expects a Node environment.
The README is also unusually candid about prebuilt binaries being potentially stale. vcpkg and conan both carry recipes, libgit2 is in Homebrew, and most Linux distributions package it, but the README warns these versions may be outdated and recommends the latest where possible. For a library linked into a shipped product, the warning is well placed, since a distribution package pinned to an old release can carry the unescaped SSH transport described above.
The tree shows what the project invests in. `src/` and `include/` are the library itself, `tests/` and `benchmarks/` are the verification work, `fuzzers/` is a category most C projects of this vintage do not have, and `deps/` holds vendored dependencies. There are three separate editor and tooling directories, `.devcontainer/`, `.vscode/` and a `script/` directory, plus `ci/` and `cmake/` for the build system. `docs/` and `api.docurium` point at generated API documentation, and `AUTHORS` alongside `FUNDING.json` shows a project with institutional process as well as individual contributors.
The presence of `fuzzers/` next to `tests/` is the most telling item. Fuzzing is how you find the parsing bugs that a unit test suite written alongside the parser will never surface, which matters most for a library whose input is attacker-influenced data like a packfile from a clone.
Threading, conventions and where the docs take over
The README's table of contents lists Threading and Conventions as top-level sections alongside Initialization, which tells you the project treats the rules for using it as first-class documentation rather than as footnotes. Threading is treated that way for a reason. libgit2 objects are not thread-safe in the general case, and the library offers mechanisms to make concurrent use safe rather than pretending the problem does not exist. Reading that section before designing a parallel architecture will save you the debugging session otherwise.
The build documentation is unusually complete, with dedicated sections for macOS, iOS, Android and MinGW, plus separate subsections for compiler and linker options and for advanced usage. Embedding a C library into four platforms with four different toolchains is genuinely fiddly, and a project that writes the MinGW section is one that has done that work rather than assumed it.
Support channels are listed concretely: an IRC channel on libera, a Slack workspace, API documentation at libgit2.org, and a Stack Overflow tag. The README asks that GitHub Issues be used for bug reports rather than for help, and asks that reports include sample code and a repository link where possible, which is a request that says something about the quality of triage the project expects.
What is not in the README is as important. There is no tutorial, no API walkthrough, and no architecture document. The README is a description, a build guide, a signpost to the manual and the API docs, and a licence explanation. For a library aimed at developers rather than at end users, that division is reasonable, but it does mean you should plan to spend time in the API documentation rather than expecting the README to teach you the library.
Editorial conclusion
libgit2 solves a specific problem that shelling out to git does not: putting Git inside a process that needs object-level access without spawning a subprocess per operation. For a forge, a GUI client or a tool that reads history as structured data, that is a capability you cannot get any other way in a language with a good binding. The two things to settle before committing are the licence, where GitHub cannot classify the project and the README explains the linking exception instead, and the scope, since the README is explicit that implementing Git the way Git does is outside what this library aims for. Start from the CMake build, which the README describes as uncomplicated, and bind upward from C rather than binding in C.
Frequently asked questions
Does Git use libgit2?
No. libgit2 is a separate implementation of Git's core methods written in C, not a component of Git itself. The Git binary does not link against it. Instead, other applications such as forges and GUI clients choose to embed libgit2 instead of invoking the git executable.
Is there a Git library for Python?
Yes, pygit2, which is the Python binding for libgit2 and is one of the bindings the libgit2 README lists alongside rugged for Ruby, libgit2sharp for .NET, nodegit for Node.js and git2-rs for Rust. Each binding embeds libgit2 rather than wrapping the git binary.
What licence does libgit2 use?
GPLv2 with a special Linking Exception, which the README describes as a very permissive licence. The exception is the operative part: you can link against libgit2 from any software, including proprietary software, without that software falling under the GPL, while modifications to libgit2 itself remain covered by the GPL. GitHub reports the licence field as NOASSERTION because no standard category fits.
How do I build libgit2 from source?
Create a build directory under the source tree, run cmake in it, then build. The README lists CMake, Python and a C compiler as the prerequisites, and states that libgit2 is C90 and should compile on most compilers, with Visual Studio, Xcode, and gcc or clang recommended on their respective platforms.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/libgit2-libgit2)