Git 2.38: Scalar arrives, and rebasing gets branch-aware
The latest Git release, version 2.38, is now available with contributions from more than 92 developers, two dozen of whom are new to the project. Two additions stand out: a built-in tool for managing large repositories, and a long-requested option for keeping dependent branches connected when you rebase.
Scalar brings large-repo settings into core Git
Git has accumulated a long list of performance features over the years, but figuring out which ones to enable for a given repository can be a chore. Scalar, now shipping with Git for the first time, packages the most impactful settings for large repositories into one command.
For a new clone with Scalar’s defaults, run:
$ scalar clone /path/to/repo
That gives you a sparse checkout by default; pass --full-clone to skip the sparse setup. If you already have a repository and want Scalar’s recommended configuration applied to it, use:
$ cd /path/to/repo
$ scalar register
The tool turns on a set of features chosen for large-repo performance: the built-in filesystem monitor, multi-pack index, commit graphs, scheduled background maintenance, partial cloning, and cone-mode sparse-checkout. Since Scalar’s configuration evolves as new Git features land, the project recommends running scalar reconfigure /path/to/repo after each new release, or scalar reconfigure -a to update every registered repository at once.
While 2.38 marks the first time Scalar is bundled with Git, the tool itself has existed for quite a while, starting life as a standalone .NET application before migrating into core Git.
Rebase dependent branches with --update-refs
Breaking a large piece of work into several stacked branches is a common workflow, but it gets messy when you need to rewrite history in an early branch. Once you rebase and squash commits in branch one, branches two and three still point at the old commits, leaving them cut off from the new history.
Consider a feature split into three branches, my-feature/part-one, my-feature/part-two, and my-feature/part-three, each building on the previous. A typical setup might look like this:
$ git log --oneline origin/main..HEAD
741a3174683 (HEAD -> my-feature/part-three) Part 3: all done!
1ff073007eb Part 3: step two
880c07e326f Part 3: step one
40529bd11dc (my-feature/part-two) Part 2: step two
0a92cc3acd8 Part 2: step one
eed018043ba (my-feature/part-one) Part 1: step three
646c870d69e Part 1: step two
9147f6d2eb4 Part 1: step one
If a code review comes back asking for changes to one of the patches in part one, the natural fix is a fixup! commit. But after squashing that fix into the part-one commit, the later branches no longer point to the rewritten commit, so they are left dangling from the new history:
Manually resetting each downstream branch to the new tip works for a few branches, but it becomes tedious with many branches or frequent changes. Git 2.38 adds --update-refs to git rebase, which automatically moves refs for any branches that depend on the commits being rebased. The same example run with the new flag keeps all branches connected:
If this behavior belongs in your default workflow, set the config option rebase.updateRefs to true, and Git will behave as if --update-refs was always supplied.
Summer of Code Contributions
Git 2.38 includes work from two Google Summer of Code participants. Shaoxuan Yuan focused on improving sparse index compatibility, while Abhradeep Chakraborty worked on reachability bitmap internals.
Yuan’s first task was making git rm work with the sparse index. Previously, commands that weren't sparse-index-aware had to expand the index to cover the full repository, which slowed operations in large repos. With this change, git rm only expands when necessary, moving Git closer to having all commands work efficiently with sparse checkouts by default. Yuan also tackled tricky corner cases around git mv when moving paths out of the sparse checkout's "cone" definition.
Chakraborty added an optional "lookup table" extension to Git's reachability bitmap format. Traditionally, .bitmap files don't provide a centralized list of their selected commits — each bitmap is prefixed with its corresponding commit's object ID, forcing Git to read the entire file to discover the covered commit set. The new lookup table sits at the end of the file and provides a concise list of selected commits along with the offset of their bitmaps, yielding faster loading and usage of bitmaps in benchmarks, particularly for large repositories. Chakraborty also improved the technical documentation for the .bitmap format.
Merge Tree and Bare Repository Security
The merge-tree command can now perform non-trivial merges without touching the index or working copy. Historically, it only handled trivial three-way merges, but Git 2.38 adds a --write-tree mode that uses the ort merge strategy. This mode takes two branches, computes the merge result, and outputs the resulting tree's object ID along with conflict information. The old behavior remains available via the deprecated --trivial-merge flag. This capability matters for bare repository hosting — GitHub, for instance, now uses the ort strategy to create merge commits significantly faster than its previous libgit2-based approach, which was necessary because bare repositories lack a worktree.
Security-conscious users will note a new safe.bareRepository configuration option. Bare repositories can be embedded inside other Git repositories, which is convenient for distribution but risky when cloning from untrusted sources. Git executes user-defined programs from $GIT_DIR/config, including core.fsmonitor, which specifies a filesystem monitoring hook that runs frequently during commands like git status. A malicious embedded bare repo could therefore trick a user into executing arbitrary code simply by having them cd into it and run a Git command. Setting safe.bareRepository to "explicit" restricts Git to only work with bare repositories specified via the top-level --git-dir argument; the default remains "all".
Grep and Other Command Updates
git grep now supports a -m option, short for --max-count, which limits matches shown per file. This pairs well with options like -C for context or -p for the enclosing function name. For example, to see how oid_object_info is used across files without multiple examples from the same file, you could run:
$ git grep -C3 -p -m1 oid_object_info
git ls-files gained a --format option that lets you customize its output per entry, exposing fields like object name, mode, stage in the index, and end-of-line behavior without additional scripting.
The low-level git cat-file command now respects the mailmap with the --[no]-use-mailmap option. Previously, transforming author, committer, or tagger identities to their canonical values required piping object contents through git show or similar. The mailmap feature maps name and email pairs to canonical values, which is useful for retaining authorship over historical commits after a name or email change.
Finally, the developer documentation now includes a codified set of the Git community’s code review guidelines, providing a reference for new and existing contributors on the norms for reviewing patches on the Git mailing list.
More useful details
The improvements above represent the highlights, but the 2.38 release contains many additional fixes and refinements. For a thorough overview, consult the release notes for 2.38. You can also find notes for all previous versions in the RelNotes directory of the Git source repository.



