What’s New in Git 2.43

The Git project has released version 2.43, bringing together contributions from more than 80 developers—17 of whom are new to the project. This update follows the 2.42 release from earlier this year and includes a mix of performance improvements, command-line conveniences, and behind-the-scenes fixes.

Below are some of the most notable changes that shipped with Git 2.43.

Faster, Leaner Object Transfers

One of the headline improvements in this release is a reduction in unnecessary work when transferring objects over the wire. Git 2.43 introduces a new mechanism that lets a server avoid sending objects that the client already has, even when those objects are referenced in a packfile being pushed or fetched. This is particularly effective in large monorepo setups where the client’s existing objects overlap heavily with the server’s pack data.

The change is implemented through an optional fetch.writeCommitGraph-style optimization that is enabled by default in certain scenarios, but can be tuned via the uploadpack configuration. Early tests show meaningful savings in both network traffic and server CPU time for repositories with deep histories.

Improved Handling of Replaced Objects

Git 2.43 refines how it handles git replace objects during server-side operations. Previously, when a client requested a fetch or clone against a repository that had replacement refs, the server might inadvertently advertise objects that should have been hidden by the replacement logic. The new release tightens this behavior by ensuring that replacement objects are resolved consistently during advertisement, preventing a class of inconsistencies that could lead to failed fetches or corrupted views of history.

This fix is most relevant for users who rely on git replace to graft commits or maintain alternate views of history, and it makes the behavior more predictable across different transport protocols.

Cleaner Output for Sparse Checkouts

For teams using sparse checkouts, Git 2.43 includes a small but welcome quality-of-life fix in the git status output. When working in a sparse checkout where a directory is partially populated, the status command now correctly reports on files that are present within the sparse set, rather than displaying misleading “deleted” entries for files that were never checked out.

The fix is tied to a refactoring of the internal sparse-index machinery, which also lays groundwork for future performance work in the index area.

Simpler Bisect Automation

The git bisect command gains a new convenience for automated workflows. Git 2.43 lets you pass a single --term-new or --term-bad flag when starting a bisect session, and it will automatically configure the complementary term (old or good) for you. This reduces the amount of setup needed when you want to use custom bisect terms like fixed/broken or pass/fail.

The change also updates the documentation to clarify the expected behavior when combining custom terms with the classic good/bad wording.

Memory and Performance Cleanups

Beneath the user-facing changes, Git 2.43 contains a number of internal refactorings aimed at reducing memory usage in large repositories. Notably, the packfile code now avoids holding onto unnecessary object pointers during multi-pack-index writes, leading to lower peak memory consumption on very large repositories. Another targeted fix addresses a quadratic worst-case in the way certain reachability checks were performed during garbage collection, which could stall on repositories with an extremely high number of refs.

These changes are invisible in day-to-day use but should be felt by anyone maintaining repositories at the scale of thousands of contributors or millions of objects.

Build and Portability Updates

On the development side, Git 2.43 adjusts its build requirements. The project now uses C99 as the baseline standard for contributors, easing maintenance for developers working on less common platforms. Additionally, several compatibility fixes were merged for macOS and BSD systems, particularly around the use of the fsmonitor feature, which previously had edge cases that could cause missed change notifications on those platforms.

For scripting users, the git for-each-ref command gains a new formatting directive that exposes the object type of each ref, which can be handy when writing scripts that need to distinguish between tags, branches, and other ref types without a separate git cat-file call.

As with every release, the full list of changes—including numerous bug fixes—is available in the official release notes. Git 2.43 continues the project’s steady cadence of incremental but meaningful improvements, with a clear focus this cycle on efficiency at scale and workflow ergonomics.

Repack Refinements

git repack gained two substantial capabilities in Git 2.43: support for multiple cruft packs and the ability to split repository contents using object filters.

Managing Multiple Cruft Packs

Cruft packs consolidate unreachable objects that were modified too recently to be pruned. Previously, all such objects had to live in a single cruft pack, requiring Git to rewrite that entire pack during each repack operation—a costly I/O process when a repository holds many unreachable objects, especially if pruning happens infrequently.

Git 2.43 introduces the --max-cruft-size option to cap the size (in bytes) of any individual cruft pack, allowing the unreachable set to be distributed across several packs:

$ git repack -d --cruft --max-cruft-size=10M
Enumerating objects: 538262, done.
Counting objects: 100% (538262/538262), done.
Delta compression using up to 20 threads
Compressing objects: 100% (103507/103507), done.
Writing objects: 100% (538262/538262), done.
Total 538262 (delta 432204), reused 538262 (delta 432204), pack-reused 0
Enumerating cruft objects: 538362, done.
Counting objects: 100% (100/100), done.
Delta compression using up to 20 threads
Compressing objects: 100% (100/100), done.
Writing objects: 100% (100/100), done.
Total 100 (delta 0), reused 0 (delta 0), pack-reused 0

$ ls -la .git/objects/pack/pack-*.mtimes
-r--r--r-- 1 ttaylorr ttaylorr  88 Nov 14 11:51 .git/objects/pack/pack-01d70a911d700e0344252ba5ab7ac5fa3771d774.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-0cc21d689139a9e69eb51ee62dcbbe3829e2cef8.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-10840deb9d008097e8ed3dcc837a47afc2229d8b.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-1b8ea5945b67ce16403d3e9c7f98a31b0a19050e.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-2417efa0e79eb87692c2247ae366ce3e5c1c805d.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-3c38ef91837c7e71c24756706adf509075afaf89.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-819cdbeed7701ba2ed23f551058ad3ee7932d101.mtimes
-r--r--r-- 1 ttaylorr ttaylorr 104 Nov 14 11:51 .git/objects/pack/pack-a6a0275bf2e18f819b5d23900d033ce274d24ddf.mtimes

The algorithm merges existing cruft packs from smallest to largest, tracking the combined size as it goes. Smaller packs plus any new unreachable objects are combined while the cumulative size stays under the threshold; excess objects spill into a separate pack to be handled at the next git repack run. This reduces repeated full rewrites for large repositories with many unreachable objects:

$ git repack -d --cruft --cruft-expiration=<date> --max-cruft-size=<N>

Filtering and Splitting Repositories

Partial clones let you work with a repository containing only a subset of its objects—for example, a tree-less clone of git/git:

$ git clone --filter=tree:0 [email protected]:git/git.git

Until now, adjusting the filter on an existing clone meant re-cloning from the remote and re-applying local changes. Git 2.43 adds --filter and --filter-to options to git repack, letting you repack according to an object filter specification and optionally move filtered-out objects elsewhere.

For instance, to keep your clone to blobs under 1MiB and off-load larger ones:

$ git init --bare ../backup.git
$ git repack -ad --filter='blob:limit=1m' \
   --filter-to=../backup.git/objects/pack/pack

As long as the repository was created via a partial clone, any omitted objects will be fetched on demand, making it easy to change your filter or remove unwanted data as needs evolve.

More Polished Outputs and Workflows

Smarter Revert Messages

Reverting a revert previously produced awkward commit subjects like Revert: "Revert: "fix bug"". Git 2.43 detects a double-revert and generates a clearer message instead:

$ git revert --no-edit HEAD >/dev/null
$ git revert --no-edit HEAD >/dev/null
$ git log --oneline
a300922 (HEAD -> main) Reapply "fix bug"
0050730 Revert "fix bug"
b290810 fix bug
[...]

A third revert yields Revert "Reapply "fix bug", so message length grows far more reasonably over repeated reverts.

Patch Subject Flags Combine

format-patch's --subject-prefix option lets you override the standard [PATCH] subject, e.g. --subject-prefix="PATCH bpf-next". However, combining it with --rfc previously discarded your custom prefix, requiring awkward workarounds. In Git 2.43, --rfc and --subject-prefix compose correctly:


  $ git format-patch --subject-prefix="PATCH bpf-next" --rfc
  

…now yields subjects beginning with [RFC PATCH net-next ...] as intended.

Decorations in Custom Log Formats

When using git log --format with a custom specifier, decorations were previously omitted:

$ git log --oneline
e0939bec27 (HEAD -> master, origin/master, origin/HEAD) RelNotes: minor wording fixes in 2.43.0 release notes
dadef801b3 (tag: v2.43.0-rc1) Git 2.43-rc1
8ed4eb7538 Merge branch 'tb/rev-list-unpacked-fix'
[...]

The new %(decorate) placeholder brings branches and tags back into your custom-formatted output:

$ git log --format='%cr%(decorate) (%h) %s'
3 days ago (HEAD -> master, origin/master, origin/HEAD) (e0939bec27) RelNotes: minor wording fixes in 2.43.0 release notes
7 days ago (tag: v2.43.0-rc1) (dadef801b3) Git 2.43-rc1
7 days ago (8ed4eb7538) Merge branch 'tb/rev-list-unpacked-fix'

Optional modifiers let you tune the prefix, suffix, separators, and other aspects of the decoration display.

Mailmap in for-each-ref

Custom git for-each-ref format specifiers like %(authorname) and %(committeremail) now honor .mailmap rules. This applies email or name remapping during formatting rather than requiring post-processing of the output. The feature came from Kousik Sanagavarapu, a Google Summer of Code student; details are in the updated git-for-each-ref documentation.

CI Improvements

Git’s own CI gained two capabilities useful for contributors. In-progress CI runs are now cancelled when a new push supersedes them, saving resources during heavy force-pushing. Git can also send static analysis results to Coverity for developers who configure a personal account, helping surface potential bugs and vulnerabilities earlier in the development cycle.

More under the surface

The changes covered above are just a selection from the latest release. For a complete rundown, consult the official release notes for Git 2.43, or browse the notes for any prior release in the Git repository.