NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1828 most downloaded on PyPI
Python bindings for libgit2.
Last release 22 days ago
12 Sep 2026
Ships fairly regularly
a new release about every 2 months
Nearly every release is documented
notes for 59 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
15 years old
91 releases · first in 2012
New exception hierarchy: AlreadyExistsError , InvalidSpecError , InvalidError , NotFoundError , AmbiguousError , AuthError , and CertificateError all
Update wheels to libgit2 1.9.7
New exception hierarchy: AlreadyExistsError, InvalidSpecError,
InvalidError, NotFoundError, AmbiguousError, AuthError, and
CertificateError all inherit from GitError and the appropriate Python
built-in exception (ValueError/KeyError) for backward compatibility
#830
Fix DiffDelta.is_binary and DiffDelta.flags returning stale values for
deltas obtained from Diff.deltas; flags are now loaded lazily
#962
#1100
Fix repo.submodules.get() and name in repo.submodules raising
AlreadyExistsError when a repository exists at the submodule path but was
never registered as a submodule; they now return None and False
respectively as documented
#1487
Fix leaks and crashes in error paths
#1478
#1479
#1480
#1481
Fix custom ODB and refdb backend callbacks overwriting a pending Python
exception (e.g. RuntimeError) with a stale libgit2 error message.
Documentation fixes
#1490
CI (macOS): build architecture-specific OpenSSL/libssh2/libgit2
dependencies instead of universal binaries, producing smaller wheels.
One column per quarter.
Remove deprecated pygit2.legacyenums module and GIT_* constants, use pygit2.enums instead
New RemoteCallbacks.custom_headers()
#1465
New rebase API: Repository.rebase_init(...), Repository.rebase_open(...),
Rebase, and RebaseOperation
#1483
Fix Config.snapshot() for non-repository configs, allow PathLike in
Config.__init__(), and improve config documentation
#1468
Fix UnicodeDecodeError with non-UTF-8 file paths in Repository.status(),
DiffFile.path, index paths, checkout callbacks, and related APIs
#1451
#1469
Fix enums.CheckoutStrategy.CONFLICT_STYLE_ZDIFF3, which was mistakenly
bound to the DIFF3 constant
#1483
Fix crashes and reference-lifetime bugs in custom refdb backends
#1471
#1474
#1475
#1476
Update wheels to libgit2 1.9.6 and OpenSSL 3.5.7
Add riscv64 wheels
#1463
Breaking changes:
Remove deprecated pygit2.legacyenums module and GIT_* constants,
use pygit2.enums instead
Remove deprecated support for passing str to Repository.merge(...),
pass a Commit, Oid, or Reference object instead
Repository.merge_file_from_index(...) now returns MergeFileResult by
default; pass use_deprecated=True for the previous string return, now
deprecated.
Remove deprecated Remote.ls_remotes(...), use Remote.list_heads(...)
instead
Remove pygit2.to_bytes(...) and pygit2.to_str(...); they were undocumented
accidental public APIs
Fix refcount and error handling issues in filter_register(...)
Update wheels to libgit2 1.9.2 and OpenSSL 3.5
CI: build ppc wheels always
CI: build ppc wheels always
Add support for Python 3.14 and drop 3.10
Add Linux musl wheels for AArch64
Add Windows wheels for AArch64; CI: build Windows wheels with cibuildwheel on GitHub #1423
New Repository.transaction() context manager, returns new ReferenceTransaction
#1420
CI: add GitHub releases and other improvements #1433 #1432 #1425 #1431
Breaking changes:
IndexEntry.hex, use str(entry.id) instead of entry.hexDeprecations:
IndexEntry.oid, use entry.id instead of entry.oidRemote.ls_remotes(...) is deprecated, use Remote.list_heads(...):
Add support for almost all global options #1409
Now it's possible to set Submodule.url = url
#1395
New RemoteCallbacks.push_negotiation(...)
#1396
New optional boolean argument connect in Remote.ls_remotes(...)
#1396
New Remote.list_heads(...) returns a list of RemoteHead objects
#1397
#1410
Documentation fixes #1388
Typing improvements #1387 #1389 #1390 #1391 #1392 #1393 #1394 #1398 #1399 #1400 #1402 #1403 #1406 #1407 #1408
Deprecations:
Remote.ls_remotes(...) is deprecated, use Remote.list_heads(...):
# Before
for head in remote.ls_remotes():
head['name']
head['oid']
head['loid'] # None when local is False
head['local']
head['symref_target']
# Now
for head in remote.list_heads():
head.name
head.oid
head.loid # The zero oid when local is False
head.local
head.symref_target
Now Repository.merge_file_from_index(...) returns a MergeFileResult object when called with use_deprecated=False #1376
Update wheels to libgit2 1.9.1 and OpenSSL 3.3
New Index.remove_directory(...)
#1377
New Index.add_conflict(...)
#1382
Now Repository.merge_file_from_index(...) returns a MergeFileResult object when
called with use_deprecated=False
#1376
Deprecations:
Update your code:
# Before
contents = Repository.merge_file_from_index(...)
# Now
result = Repository.merge_file_from_index(..., use_deprecated=False)
contents = result.contents
At some point in the future use_deprecated=False will be the default.
Passing str to Repository.merge(...) is deprecated, instead pass an oid object (or a commit, or a reference) #1349
Upgrade Linux Glibc wheels to manylinux_2_28
Add RemoteCallbacks.push_transfer_progress(...) callback
#1345
New bool(oid)
#1347
Now Repository.merge(...) accepts a commit or reference object
#1348
New threads optional argument in Remote.push(...)
#1352
New proxy optional argument in clone_repository(...)
#1354
New optional arguments context_lines and interhunk_lines in Blob.diff(...) ; and
now Repository.diff(...) honors these two arguments when the objects diffed are blobs.
#1360
Now Tree.diff_to_workdir(...) accepts keyword arguments, not just positional.
Fix when a reference name has non UTF-8 chars #1329
Fix condition check in Repository.remotes.rename(...)
#1342
Add codespell workflow, fix a number of typos #1344
CI: Use ARM runner for tests and wheels #1346
Deprecations:
Repository.merge(...) is deprecated,
instead pass an oid object (or a commit, or a reference)
#1349Breaking changes:
flag has been renamed to flags in Blob.diff(...) and
Blob.diff_to_buffer(...)Add certificate_check callback to Remote.ls_remotes(...) #1326
New Repository.hashfile(...) #1298
Add support for Python 3.13
Drop support for Python 3.9
New Repository.hashfile(...)
#1298
New Option.GET_MWINDOW_FILE_LIMIT and Option.SET_MWINDOW_FILE_LIMIT
#1312
Fix overriding certificate_check(...) callback via argument to RemoteCallbacks(...)
#1321
Add py.typed #1310
Fix discover_repository(...) annotation
#1313
New Repository.revert(...) #1297
New Repository.revert(...)
#1297
New optional depth argument in submodules add() and update() methods
#1296
Now Submodule.url returns None when the submodule does not have a url
#1294
Fix use after free bug in error reporting #1299
Fix Submodule.head_id when the submodule is not in the current HEAD tree
#1300
Fix Submodule.open() when subclassing Repository
#1295
Fix error in the test suite when running with address sanitizer #1304 #1301
Annotations and documentation fixes #1293
Many deprecated features have been removed, see below
Many deprecated features have been removed, see below
Upgrade to libgit2 v1.8.1
New push_options optional argument in Repository.push(...)
#1282
New support comparison of Oid with text string
Fix CheckoutNotify.IGNORED
#1288
Use default error handler when decoding/encoding paths #537
Remove setuptools runtime dependency #1281
Coding style with ruff #1280
Add wheels for ppc64le #1279
Fix tests on EPEL8 builds for s390x #1283
Deprecations:
IndexEntry.hex, use str(IndexEntry.id)Breaking changes:
Remove deprecated oid.hex, use str(oid)
Remove deprecated object.hex, use str(object.id)
Remove deprecated object.oid, use object.id
Remove deprecated Repository.add_submodule(...), use Repository.submodules.add(...)
Remove deprecated Repository.lookup_submodule(...), use Repository.submodules[...]
Remove deprecated Repository.init_submodules(...), use Repository.submodules.init(...)
Remove deprecated Repository.update_submodule(...), use Repository.submodules.update(...)
Remove deprecated constants GIT_OBJ_XXX, use ObjectType
Remove deprecated constants GIT_REVPARSE_XXX, use RevSpecFlag
Remove deprecated constants GIT_REF_XXX, use ReferenceType
Remove deprecated ReferenceType.OID, use instead ReferenceType.DIRECT
Remove deprecated ReferenceType.LISTALL, use instead ReferenceType.ALL
Remove deprecated support for passing dicts to repository's merge(...),
merge_commits(...) and merge_trees(...). Instead pass MergeFlag for flags, and
MergeFileFlag for file_flags.
Remove deprecated support for passing a string for the favor argument to repository's
merge(...), merge_commits(...) and merge_trees(...). Instead pass MergeFavor.
Deprecate ReferenceType.OID, use ReferenceType.DIRECT
Remove deprecated Repository.create_remote(...) function, use instead Repository.remotes.create(...)
Drop support for Python 3.8
Add Linux wheels for musl on x86_64 #1266
New Repository.submodules namespace
#1250
New Repository.listall_mergeheads(), Repository.message,
Repository.raw_message and Repository.remove_message()
#1261
New pygit2.enums supersedes the GIT_ constants
#1251
Now Repository.status(), Repository.status_file(),
Repository.merge_analysis(), DiffFile.flags, DiffFile.mode,
DiffDelta.flags and DiffDelta.status return enums
#1263
Now repository's merge(), merge_commits() and merge_trees()
take enums/flags for their favor, flags and file_flags arguments.
#1271
#1272
Fix crash in filter cleanup #1259
Breaking changes:
Repository.create_remote(...) function, use
instead Repository.remotes.create(...)Deprecations:
Deprecate Repository.add_submodule(...), use Repository.submodules.add(...)
Deprecate Repository.lookup_submodule(...), use Repository.submodules[...]
Deprecate Repository.init_submodules(...), use Repository.submodules.init(...)
Deprecate Repository.update_submodule(...), use Repository.submodules.update(...)
Deprecate GIT_* constants, use pygit2.enums
Passing dicts to repository's merge(...), merge_commits(...) and merge_trees(...)
is deprecated. Instead pass MergeFlag for the flags argument, and MergeFileFlag for
file_flags.
Passing a string for the favor argument to repository's merge(...), merge_commits(...)
and merge_trees(...) is deprecated. Instead pass MergeFavor.
New API for filters in Python #1237 #1244
depth optional argument for
clone_repository(...) and Remote.fetch(...)
#1245
#1246init(...), update(...) and reload(...) functions
#1248Walker.__next__
#1249Repository
#1247- Support Python 3.12 - Documentation updates #1242
Fix crash in reference rename #1233
Don\'t distribute wheels for pypy, only universal wheels for macOS
Update wheels to bundle libssh2 1.11.0 and OpenSSL 3.0.9
Remote.save()
#1219Fix segfault in signature when encoding is incorrect #1210
Update Linux wheels to bundle OpenSSL 3.0.8
ConflictCollection.__contains__
#1181Repository.references.iterator(...)
#1191favor, flags and file_flags optional arguments for
Repository.merge(...)
#1192keep_all and paths optional arguments for
Repository.stash(...)
#1202Repository.state()
#1204Repository.write_archive(...) performance
#1183Fix Linux wheels, downgrade to manylinux 2_24 #1176
Update Linux wheels to manylinux 2_28 #1136
Signature
#1173raise_error in Repository.applies(...)
#1166Repository.remotes.names()
#1159refname argument in
RemoteCallbacks.push_update_reference(...) is a string, not bytes
#1168pygit2/decl/pack.h
#1163Fix segfault in Signature repr #1155
Add support for GIT_OPT_GET_OWNER_VALIDATION and GIT_OPT_SET_OWNER_VALIDATION #1150
New Repository.create_commit_string(...) and Repository.create_commit_with_signature(...) #1142
Type hints: added to C code and Branches/References #1121 #1132
Signature supports str() and repr()
#1135parse_diff
#1131Documentation, new recipes for committing and cloning #1125
Rename RemoteCallbacks.progress(...) callback to .sideband_progress(...) #1120
RemoteCallbacks.progress(...) callback to
.sideband_progress(...)
#1120Repository.merge_base_many(...) and
Repository.merge_base_octopus(...)
#1112Repository.listall_stashes()
#1117Backward incompatible changes:
RemoteCallbacks.progress(...) callback has been renamed to
RemoteCallbacks.sideband_progress(...). This matches the
documentation, but may break existing code that still uses the old
name.Universal wheels for macOS #1109
New Repository.amend_commit(...) #1098
Linux wheels now bundled with libssh2 1.10.0 (instead of 1.9.0)
location in Repository.applies(..) and
Repository.apply(..)
#1091Caveats:
Fix a number of reference leaks
Breaking changes:
read to
read_cb, write to write_cb, and so on.Remove deprecated GIT_CREDTYPE_XXX constants, use GIT_CREDENTIAL_XXX instead.
proxy argument in Remote methods
#642
#1063
#1069build.sh scriptBreaking changes:
GIT_CREDTYPE_XXX constants, use
GIT_CREDENTIAL_XXX instead.Patch.patch getter, use Patch.text instead.New PackBuilder class and Repository.pack(...) #1048
PackBuilder class and Repository.pack(...)
#1048Config.delete_multivar(...)
#1056Repository.is_shallow
#1058message argument in
Repository.create_reference(...)
#1061
#1062Breaking changes:
Index.add(...) raise TypeError instead of AttributeError
when arguments are of unexpected typeUpgrade to libgit2 1.1, new GIT_BLAME_IGNORE_WHITESPACE constant #1040
New Repository.add_submodule(...) #1011
Repository.add_submodule(...)
#1011Repository.applies(...)
#1019Repository.revparse(...) and Repository.revparse_ext(...)
#1022flags and file_flags arguments in
Repository.merge_commits and Repository.merge_trees
#1008Reference.raw_target, Repository.raw_listall_branches(...)
and Repository.raw_listall_references(); allow bytes in
Repository.lookup_branch(...) and Repository.diff(...)
#1029GIT_BLAME_FIRST_PARENT and GIT_BLAME_USE_MAILMAP constants
#1031IndexEntry supports repr(), str(), == and !=
#1009Object supports repr()
#1022Repository.apply(...)
#1033Repository.listall_submodules()
commit 32133974OdbBackend.refresh() and
Worktree_is_prunable commit fed0c19cDeprecate Repository.create_remote(...), use instead Repository.remotes.create(...)
Object.raw_name when not reached through a tree
#1002Deprecations:
Repository.create_remote(...), use instead
Repository.remotes.create(...)GIT_CREDTYPE_XXX constants, use GIT_CREDENTIAL_XXX
instead.Drop support for Python 3.5 #991
index optional parameter in Repository.checkout_index
#987pip install pygit2
#986Fix crash in tree iteration #984 #980
Continued work on custom odb backends #948
Diff.patchid getter
#960
#877settings.disable_pack_keep_file_checks(...)
#908GIT_DIFF_ and GIT_DELTA_ constants
#738_pygit2 to pygit2._pygit2
#978Requirements changes:
Breaking changes:
In the rare case you're directly importing the low level _pygit2,
the import has changed:
# Before
import _pygit2
# Now
from pygit2 import _pygit2
Fix memory leak in DiffFile #943
Fix enumerating tree entries with submodules #967
- Fix build in Mac OS #963
Drop Python 2.7 and 3.4 support, six no longer required #941
/ operator to traverse trees
#903
#924Branch.raw_branch_name
#954Index.remove_all()
#920Remote.ls_remotes(..)
#935
#936Repository.lookup_reference_dwim(..) and
Repository.resolve_refish(..)
#922
#923Repository.odb returns new Odb type instance. And new
OdbBackend type.
#940
#942Repository.references.compress()
#961Breaking changes:
Now the Repository has a new attribute odb for object database:
# Before
repository.read(...)
repository.write(...)
# Now
repository.odb.read(...)
repository.odb.write(...)
Now Tree[x] returns a Object instance instead of a TreeEntry;
Object.type returns an integer while TreeEntry.type returned a
string:
# Before
if tree[x].type == 'tree':
# Now
if tree[x].type == GIT_OBJ_TREE:
if tree[x].type_str == 'tree':
Renamed TreeEntry._name to Object.raw_name:
# Before
tree[x]._name
# Now
tree[x].raw_name
Object comparison is done by id. In the rare case you need to do tree-entry comparison or sorting:
# Before
tree[x] < tree[y]
sorted(list(tree))
# Now
pygit2.tree_entry_cmp(x, y) < 0
sorted(list(tree), key=pygit2.tree_entry_key)
Fix crash in reflog iteration #901
New Patch.text returns the contents of the patch as a text string, deprecates [Patch.patch]{.title-ref} #790 #893
Repository.write_archive(..) keeps the file mode
#616
#898Patch.data returns the raw contents of the patch as a byte
string #790
#893Patch.text returns the contents of the patch as a text string,
deprecates [Patch.patch]{.title-ref}
#790
#893Deprecations:
Patch.patch is deprecated, use Patch.text insteadAdd binary wheels for Linux #793 #869 #874 #875 #883
pygit2.Mailmap, see documentation
#804Repository.apply(...) wraps git_apply(..)
#841
#843Repository.merge_analysis(...) accepts an optional reference
parameter #888
#891Repository.add_worktree(...) accepts an optional reference
parameter #814
#889Breaking changes:
Remove deprecated [Reference.get_object()]{.title-ref}, use [Reference.peel()]{.title-ref} instead
pygit2.LIBGIT2_VER tuple
#845
#848paths optional argument in Repository.checkout()
#858
#859Breaking changes:
Move to pytest, drop support for Python 3.3 and cffi 0.x #824 #826 #833 #834
Submodule.head_id
#817Remote.prune(...)
#825pygit2.reference_is_valid_name(...)
#827AlreadyExistsError and InvalidSpecError
#828
#829Reference.raw_name, Reference.raw_shorthand, Tag.raw_name,
Tag.raw_message and DiffFile.raw_path
#840Repository.descendant_of(...) if commit
doesn't exist #822
#842Breaking changes:
Tag._message, replaced by Tag.raw_messageAdd support for Python 3.7 #809
Object.short_id
#799
#806
#807Repository.descendant_of and Repository.branches.with_commit
#815
#816clone_repository(...)
#818Now discover_repository returns None if repository not found, instead of raising KeyError #531
- Update to libgit2 v0.27 #783 - Fix for GCC 4 #786
Now iterating over a configuration returns ConfigEntry objects #778
Backward incompatible changes:
Now iterating over a configuration returns ConfigEntry objects
#778
# Before
for name in config:
value = config[name]
# Now
for entry in config:
name = entry.name
value = entry.value
Other changes:
Commit.gpg_signature
#766Diff.parse_diff(...)
#774callbacks in
Repository.update_submodules(...)
#763KeypairFromMemory credentials
#771Improvements to Patch.create_from #753 #756 #759
New property Patch.patch #739 #741
Drop support for Python 3.2, add support for cffi 1.10 #706 #694
New support for stash: repository methods stash, stash_apply, stash_drop and stash_pop #695
stash, stash_apply,
stash_drop and stash_pop
#695init_submodules and update_submodules
#692Repository.branches
and Repository.references
#700
#701init_repository crash on None input
#688
#697Your coding agent can read these notes before it upgrades. Set up the MCP server →