{"id":2218,"library":"pygit2","title":"pygit2","description":"pygit2 is a set of Python bindings for libgit2, a portable, pure C implementation of the Git core methods. It provides a low-level, plumbing-focused API for interacting with Git repositories. The library is actively maintained, with version 1.19.2 being the latest as of March 2026, and typically sees multiple minor releases per year, often in sync with libgit2 updates and bug fixes. It supports Python versions 3.11 through 3.14, and PyPy3 7.3+.","status":"active","version":"1.19.2","language":"en","source_language":"en","source_url":"https://github.com/libgit2/pygit2","tags":["git","version control","bindings","libgit2"],"install":[{"cmd":"pip install pygit2","lang":"bash","label":"Install with pip"},{"cmd":"brew install libgit2 # On macOS, then pip install pygit2\n# For other OSes, install libgit2 development packages (e.g., libgit2-dev on Debian/Ubuntu, libgit2-devel on Fedora/RHEL) if binary wheel is not available.","lang":"bash","label":"Install with system libgit2 (if building from source)"}],"dependencies":[{"reason":"pygit2 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.","package":"libgit2","optional":false},{"reason":"Used for Python Foreign Function Interface to interact with libgit2.","package":"cffi","optional":false}],"imports":[{"symbol":"Repository","correct":"from pygit2 import Repository"},{"symbol":"init_repository","correct":"from pygit2 import init_repository"},{"symbol":"Signature","correct":"from pygit2 import Signature"},{"note":"While `GitError` can be imported from `_pygit2`, the public API exposes it directly under `pygit2`.","wrong":"from pygit2._pygit2 import GitError","symbol":"GitError","correct":"from pygit2 import GitError"},{"symbol":"enums","correct":"from pygit2 import enums"}],"quickstart":{"code":"import pygit2\nimport os\nimport shutil\nimport tempfile\nfrom pygit2 import enums\n\ndef create_and_commit_repo():\n    # Create a temporary directory for the repository\n    repo_path = tempfile.mkdtemp()\n    print(f\"Creating repository at: {repo_path}\")\n\n    try:\n        # Initialize a new bare repository\n        # For a non-bare repo with a working directory, use `bare=False`\n        repo = pygit2.init_repository(repo_path, bare=False)\n\n        # Configure author and committer details\n        author = pygit2.Signature(\"Test User\", \"test@example.com\")\n        committer = pygit2.Signature(\"Test User\", \"test@example.com\")\n\n        # Create a file in the working directory\n        file_path = os.path.join(repo_path, \"README.md\")\n        with open(file_path, \"w\") as f:\n            f.write(\"# My New Repository\\n\\nThis is a test repository.\")\n\n        # Add the file to the index\n        repo.index.add(\"README.md\")\n        repo.index.write()\n\n        # Create a tree from the index\n        tree = repo.index.write_tree()\n\n        # Create the initial commit\n        # For an initial commit, the parents list is empty, and HEAD is used\n        commit_id = repo.create_commit(\n            'HEAD',              # Reference to update\n            author,              # Author signature\n            committer,           # Committer signature\n            'Initial commit',    # Commit message\n            tree,                # Tree object for the commit\n            []                   # Parent commits (empty for initial commit)\n        )\n\n        print(f\"Initial commit created with ID: {commit_id}\")\n\n        # Checkout the branch to populate the working directory\n        repo.checkout('refs/heads/main') # Or 'refs/heads/master' depending on default branch\n        print(f\"Repository content in working directory: {os.listdir(repo_path)}\")\n\n    finally:\n        # Clean up the temporary directory\n        shutil.rmtree(repo_path)\n        print(f\"Cleaned up repository at: {repo_path}\")\n\nif __name__ == \"__main__\":\n    create_and_commit_repo()","lang":"python","description":"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."},"warnings":[{"fix":"Update 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.","message":"`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.","severity":"breaking","affected_versions":"1.19.2+"},{"fix":"Replace `entry.hex` with `str(entry.id)` to get the hexadecimal representation of an index entry's OID.","message":"The `IndexEntry.hex` property has been removed. Accessing it will raise an AttributeError.","severity":"breaking","affected_versions":"1.18.0+"},{"fix":"Use `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(...)`.","message":"Several 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.","severity":"breaking","affected_versions":"1.14.0+"},{"fix":"Ensure `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`.","message":"Building 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).","severity":"gotcha","affected_versions":"All versions (when building from source)"},{"fix":"Upgrade `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).","message":"Older 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.","severity":"gotcha","affected_versions":"< 1.9.x"},{"fix":"For 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.","message":"When 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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always 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.","message":"The `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`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}