A Faster Worktree Setup and Cleaner Dirty-State Checks
Git 2.46 is out, the result of work from over 96 contributors, 31 of whom are new to the project. Among the usual spread of fixes and refinements, a few changes stand out for daily users: linked worktrees get a meaningful speedup, the plumbing commands behind common status checks behave more predictably, and the transfer protocol gains a handy debugging tool for proxy connections.
Make git worktree add Smarter and Quicker
In previous versions, when you ran git worktree add to check out a branch in a new directory, Git could end up spending a lot of time scanning the object database. Specifically, it would walk all commits that were reachable from the new worktree’s HEAD but not from any existing worktree, just to decide what needed to be checked out. In a repository with a large history, this walk could stall the command noticeably.
Git 2.46 optimizes this in a common case. When the new branch points at a commit that is already reachable from the HEAD of any linked worktree (or the main worktree), Git can skip the expensive object enumeration entirely. The reachability check itself is cheap, and for a git worktree add that simply branches from the current state, or from a commit already in use elsewhere, the setup is now dramatically faster. The change comes from a patch by Christian Couder.
A Cleaner Interface for the Dirty-State Helper
The git-status command relies on a plumbing helper, --short output, and an internal function that classifies the working tree as dirty or clean. That helper is now exposed as git status --porcelain=v2 --branch enhancements, but more directly, the logic behind the scenes has been untangled.
Previously, the function that decided whether a worktree was dirty could return an error status without giving a precise reason, forcing callers like git-sh-setup scripts and git-prompt to guess. In 2.46, the internal plumbing now reports the actual condition — such as an unstaged modification, an untracked file, or a conflicted merge — back to callers. For users, the practical effect is that scripted checks like git diff --quiet and git diff --cached --quiet now behave consistently even when the working tree contains untracked files. The messy “unknown” state that could previously leak into prompt scripts or custom tooling is gone.
Smarter Helper Process Handling
git-p4 and other tools that spawn long-running helper processes got a reliability fix. When a helper exits unexpectedly, Git now treats it as a hard failure instead of a silent prompt to retry, which could previously lead to confusing interactions with interactive prompts in the middle of a scripted operation.
Additionally, work continues on making git bisect and other commands robust to shallow clones. A handful of fixes ensure that operations like git bisect in a shallow repository no longer miscalculate the commit range they operate on.
New Debugging Support for HTTP Proxies
For users who route Git over HTTP proxies, 2.46 adds a debugging aid: trace2 logging now records proxy-related events. If you’re diagnosing an intermittent connection issue, setting GIT_TRACE2_EVENT=1 will surface the new proxy events, which show the host and port Git attempts to connect to after CONNECT negotiation. This is especially useful when a proxy is configured via the http.proxy config or the HTTPS_PROXY environment variable for https:// remotes.
The feature is paired with an update to the documentation for the trace2 subsystem, which now explicitly covers the proxy connection state machine.
Maintenance and Cleanup
On the housekeeping front, git maintenance gained a new task, git maintenance run --task=pack-refs, that packs loose refs into the packed-refs file. The task respects a new configuration option, maintenance.pack-refs, which you can set to "auto" to have the maintenance job run the pack opportunistically, or "true" to force it every run. The default remains "auto", so the operation runs only when there is a detectable benefit.
The change aims to reduce the overhead of walking refs in repositories that accumulate many loose refs over time.
Other Notable Fixes
A few smaller quality-of-life improvements round out the release:
git format-patchnow correctly handles the--min-3wayoption when combined with--color-moved.git merge-treelearned to emit an error message instead of crashing when given a non-existent tree-ish.- The
git logandgit rev-listmachinery fixed a bug where--full-historycombined with a file path could prune commits incorrectly. git statusnow reports the correct file mode for entries in a split index, fixing a discrepancy between the index and the working tree.- The
git sparse-checkoutcommand no longer leaves stray directory entries behind after a pattern update. git amgained better handling of a commit that is already applied, avoiding a spurious conflict notification.
Finally, the Git project also commemorates the release with updated documentation for the gitfaq and a refreshed gitcli man page that clarifies the precedence of command-line options.
Git 2.46 is available from the usual channels: the source tarball from kernel.org, package managers like Homebrew, or the official Git for Windows installers. As always, consult the release notes for a complete enumeration of changes.
A Shortcut for Fetch Traversals: Pseudo-Merge Bitmaps
Reachability bitmaps have long been a key optimization for fetch operations. When a client requests objects, Git must compute the set of commits, trees, and blobs that lie between what the client wants and what it already has. A naive approach walks backwards through history from each "wanted" commit, marking objects until it hits a commit reachable from the "haves." That walk works, but can become slow as history grows.
Bitmaps compress this problem: each bit represents an object, and a bitmap for a commit encodes everything reachable from it. During a traversal, when Git encounters a commit that has a bitmap, it can instantly mark that entire portion of history as reachable, skipping the individual walk. Still, not every commit gets its own bitmap—writing one for each commit is expensive—so some parts of the graph still require manual traversal.

Git 2.46 introduces experimental support for pseudo-merge bitmaps. Instead of representing a single commit, a pseudo-merge bitmap encodes the set of objects reachable from multiple commits at once. This is particularly useful for fetching several branches together: a client that wants foo, bar, and baz can be served by a single pseudo-merge that covers all three, instead of relying on three separate bitmaps or a long walk.

During traversal, Git checks whether any pseudo-merge is "usable"—meaning every commit it describes is explicitly or implicitly wanted. Once a usable pseudo-merge is found, all of its objects are marked in one step. Remaining history is still walked manually, but the heavy lifting is often done in far fewer steps. The feature is configurable through a new set of options that determine how pseudo-merges are selected and organized; it remains marked as experimental and can be enabled as follows:
# configure pseduo-merge bitmaps
$ git config bitmapPseudoMerge.all.pattern 'refs/(heads|tags)/'
$ git config bitmapPseudoMerge.all.threshold now
$ git config bitmapPseudoMerge.all.stableThreshold never
# then generate a new *.bitmap file
$ git repack -adb
Spring Cleaning for git config
The git config command is far more than a simple configuration setter. It can list settings, fetch single values or groups matching a regex, unset keys, rename or delete sections, and open files in an editor. Previously, these capabilities were spread across many command-line flags like --get, --get-all, --unset, and --remove-section.
Git 2.46 replaces this sprawl with a sub-command interface. For example, listing all settings is now git config list; retrieving a single value is git config get <name>; and narrowing by regex is done with --regexp on the get sub-command. Existing invocations remain compatible, but the new structure groups related tasks under clearer, top-level commands.
Richer Credential Helper Protocol
Git's credential helper mechanism traditionally supports username/password-based HTTP auth. For services requiring Bearer tokens, users were forced to store secrets in plaintext via http.extraHeader—far from ideal. In 2.46, the credential helper protocol is extended with two new fields, authtype and credential, along with support for holding arbitrary per-helper state and multi-round exchanges needed for protocols like NTLM and Kerberos.
These additions allow sensitive tokens to move out of configuration files and into helper-managed storage. The protocol updates also lay groundwork for implementing more complex auth flows in the future.
Converting Repositories to Reftable
The reftable reference storage backend—still experimental—previously required initializing a new repository with git init --ref-format=reftable. Git 2.46 adds the ability to migrate an existing repository, via the new git refs migrate --ref-format=reftable command. As before, this backend offers near constant-time single-reference lookups, efficient prefix-compressed namespace scans, and atomic updates that scale with change size rather than repository total. Known limitations remain, so migrating a production repo without a fallback copy is still not advised.
Silencing All Advice at Once
Git emits "advice" messages for operations that might be confusing or risky, such as checking out a detached HEAD (shown below). While individual advice types can be disabled via their own config keys—e.g., git config set advice.detachedHead false—scripting that wanted to suppress all of them had to enumerate each setting.
$ git checkout HEAD^
Note: switching to 'HEAD^'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
[...]
Git 2.46 introduces a top-level --no-advice flag. Passing this to any Git command disables all advice messages, keeping stderr clean for scripts.
Moving Tests From Shell to Unit
Git's extensive test suite is written largely in Shell scripts, which execute tens of thousands of integration-level checks. While effective, these scripts suffer from high process-spawn overhead on platforms like Windows. Some lower-level components—such as the progress meter—also require awkward, line-oriented helpers to be testable from the shell.
Git 2.46 continues a gradual shift toward unit tests, allowing direct validation of individual subsystems without the overhead or indirection of shell-based harnesses. This conversion makes testing those low-level components faster and more focused, and is an ongoing effort across the codebase.
Beyond the headline features
The changes covered above are only a selection from Git 2.46. For a complete accounting, consult the official release notes for 2.46, or browse the notes for earlier releases in the Git source repository. Off by one — see the footnotes below. Details.
Costs worth weighing
A few of the new features carry a price tag that bears mentioning before you enable them across a large repository. For one, a particular optimization is notable because it is expensive on both ends: it requires walking through more history when producing the relevant *.bitmap files. At query time, the cost doesn't disappear either. Because bitmaps are combined with an OR operation, a proliferation of bitmaps means Git spends considerable effort decompressing and ORing them together to answer a single request. That overhead can accumulate quickly in an environment where many bitmaps are in play.
Testing depth varies
When you run the test suite, the number of executed tests is not a fixed figure. It shifts based on your environment, as some tests only run if particular packages are installed or if your file system has the required properties. For context, running make test on a typical development machine can execute more than 31,000 tests, but your mileage will depend on your specific setup.



