Install & Compatibility
Where this runs
tested against v1.18.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.150s · 34.3MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.2s · import 0.140s · 35MB
33MB installed
● package 33MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Repository
✓ from pygit2 import Repository
init_repository
✓ from pygit2 import init_repository
Signature
✓ from pygit2 import Signature
GitError
✓ from pygit2 import GitError
✗ from pygit2._pygit2 import GitError
While `GitError` can be imported from `_pygit2`, the public API exposes it directly under `pygit2`.
enums
✓ from pygit2 import enums
This quickstart demonstrates how to initialize a new Git repository, create a file, add it to the index, and make the first commit using pygit2. It also includes cleanup of the temporary repository directory.
import pygit2
import os
import shutil
import tempfile
from pygit2 import enums
def create_and_commit_repo():
# Create a temporary directory for the repository
repo_path = tempfile.mkdtemp()
print(f"Creating repository at: {repo_path}")
try:
# Initialize a new bare repository
# For a non-bare repo with a working directory, use `bare=False`
repo = pygit2.init_repository(repo_path, bare=False)
# Configure author and committer details
author = pygit2.Signature("Test User", "test@example.com")
committer = pygit2.Signature("Test User", "test@example.com")
# Create a file in the working directory
file_path = os.path.join(repo_path, "README.md")
with open(file_path, "w") as f:
f.write("# My New Repository\n\nThis is a test repository.")
# Add the file to the index
repo.index.add("README.md")
repo.index.write()
# Create a tree from the index
tree = repo.index.write_tree()
# Create the initial commit
# For an initial commit, the parents list is empty, and HEAD is used
commit_id = repo.create_commit(
'HEAD', # Reference to update
author, # Author signature
committer, # Committer signature
'Initial commit', # Commit message
tree, # Tree object for the commit
[] # Parent commits (empty for initial commit)
)
print(f"Initial commit created with ID: {commit_id}")
# Checkout the branch to populate the working directory
repo.checkout('refs/heads/main') # Or 'refs/heads/master' depending on default branch
print(f"Repository content in working directory: {os.listdir(repo_path)}")
finally:
# Clean up the temporary directory
shutil.rmtree(repo_path)
print(f"Cleaned up repository at: {repo_path}")
if __name__ == "__main__":
create_and_commit_repo()
Debug
Known issues
breaking`Odb.read(...)` now returns `enums.ObjectType` (an enum) instead of an integer for the object type. If your code expects an `int` for the object type when reading from the ODB, it will break.fixUpdate your code to expect and handle `pygit2.enums.ObjectType` when retrieving object types from `Odb.read(...)` or `Odb.read_header(...)`. For example, use `obj_type.value` if an integer is strictly required, but it's recommended to use the enum directly.
affects: 1.19.2+
breakingThe `IndexEntry.hex` property has been removed. Accessing it will raise an AttributeError.fixReplace `entry.hex` with `str(entry.id)` to get the hexadecimal representation of an index entry's OID.
affects: 1.18.0+
breakingSeveral repository methods related to remotes and submodules have been removed or deprecated in favor of accessing them through the `Repository.remotes` and `Repository.submodules` objects. E.g., `Repository.create_remote` was removed.fixUse `repo.remotes.create(...)` instead of `repo.create_remote(...)`. Similarly, replace `Repository.add_submodule(...)` with `Repository.submodules.add(...)`, `Repository.lookup_submodule(...)` with `Repository.submodules[...]`, and `Repository.update_submodule(...)` with `Repository.submodules.update(...)`.
affects: 1.14.0+
gotchaBuilding pygit2 from source requires the `libgit2` development files to be installed on your system. If these are not found, installation will fail with `fatal error: git2.h: No such file or directory`. Binary wheels are available for many platforms, but not all (e.g., macOS often requires manual `libgit2` installation via Homebrew).fixEnsure `libgit2` development packages are installed before `pip install pygit2`. On macOS, use `brew install libgit2`. On Debian/Ubuntu, use `apt-get install libgit2-dev`. On Fedora/RHEL, use `dnf install libgit2-devel`.
affects: All versions (when building from source)
gotchaOlder versions of `pygit2` (e.g., v1.4.0, often found in older Linux distributions) might use `libgit2` builds that do not support modern SSH key types (e.g., RSA SHA-1 keys are deprecated by GitHub). This can lead to `GitError: ERROR: You're using an RSA key with SHA-1, which is no longer allowed` when pushing/pulling via SSH.fixUpgrade `pygit2` and its underlying `libgit2` to a recent version (1.9.x or newer) that supports modern SSH protocols and key types. Ensure your SSH agent is running and contains compatible keys (e.g., Ed25519 or RSA SHA-2).
affects: < 1.9.x
gotchaWhen making an *initial* commit in a newly created repository, the first argument to `Repository.create_commit()` should typically be `'HEAD'` (or a specific branch name like `'refs/heads/main'`) instead of an uninitialized reference like `'refs/heads/master'` if the branch does not yet exist. Using an incorrect or non-existent ref might lead to errors or unexpected behavior if the head hasn't been established.fixFor initial commits, use `repo.create_commit('HEAD', author, committer, message, tree, [])` and then `repo.checkout('refs/heads/main')` (or desired branch) to set the head and populate the working directory. affects: All versions
gotchaThe `pygit2` library versions often track the `libgit2` C library versions. Installing a `pygit2` version that is incompatible with your system's `libgit2` version (especially when building from source) can lead to compilation errors or runtime issues. For example, `pygit2 1.19.x` is designed for `libgit2 1.9.x`.fixAlways check the `pygit2` documentation or PyPI page for the recommended `libgit2` version matching your `pygit2` installation. If installing from source, ensure your system's `libgit2` version aligns with the `pygit2` version you are trying to install.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'pygit2'
The 'pygit2' library is not installed in the Python environment where the code is being executed.
fixInstall the library using pip: `pip install pygit2`
fatal error: git2.h: No such file or directory
During installation, pip failed to find a pre-compiled binary wheel for pygit2 and attempted to build it from source, but the required libgit2 development headers are missing on the system.
fixInstall the libgit2 development package specific to your operating system, then retry the pygit2 installation. For Debian/Ubuntu: `sudo apt-get install libgit2-dev`. For Fedora/RHEL: `sudo dnf install libgit2-devel`. For macOS (with Homebrew): `brew install libgit2`. After installing the dependencies, run `pip install pygit2` again.
KeyError: 'object not found - no match for id (some_object_id)'
This error occurs when attempting to retrieve a Git object (such as a commit, blob, or tree) using an Object ID (OID) that does not exist in the repository's object database.
fixVerify that the OID is correct and corresponds to an existing object within the repository. Use `repo.get(oid)` which returns `None` for non-existent objects, rather than `repo[oid]` which raises a KeyError. Ensure the repository is fully cloned (not shallow) if you expect all history to be present.
Upgrade
Version history
1.20.0latest on PyPI · released Aug 8, 2026
Audit
Dependencies
libgit2requiredpygit2 is a binding to the libgit2 C library. While binary wheels often bundle libgit2, building from source requires a system-wide installation of libgit2 development files.
cffirequiredUsed for Python Foreign Function Interface to interact with libgit2.