A New Command for Sparse Checkout Workflows
Git 2.25 introduces a dedicated git sparse-checkout command, simplifying a workflow that previously required manually editing repository internals. The release also continues Git’s ongoing work toward mature partial clone support, an experimental feature that lets you clone and work with only the objects you need from a large repository.
How Partial Clones Work Today
Partial clones address a fundamental scaling problem: a standard git clone copies every version of every file in a repository’s history. For very large repositories, this can make cloning impractical due to network transfer and local storage costs, even when you only care about a subset of the content.
With a partial clone, the client and server cooperate in a specific way. The client must ask the server for only certain objects, and it must tolerate having an incomplete set of objects locally. The server, in turn, must understand that request and respond appropriately by omitting the objects the client doesn’t want.
For example, if your repository’s history is manageable but its working tree is too large, you can clone with this command, which skips all blobs (file contents):
$ git clone --filter=blob:none --no-checkout /your/repository/here
The --filter= flag tells the clone server which objects to omit, and you can choose from a number of qualifiers beyond blob:none. The --no-checkout flag is equally important here: without it, Git would attempt to check out the repository, discover missing objects, and try to fetch them. By skipping the checkout in this step, you create a repository on disk that has partial data but no working copy files. That’s where sparse checkout comes in.
Sparse Checkout Management
Sparse checkout is a list of file path patterns that determines which files Git populates in your working copy. It operates much like a .gitignore file, except that instead of excluding files from version control, it limits which tracked files appear in your checkout. The historical catch was that setting this up involved writing complex patterns directly into .git/info/sparse-checkout. To avoid checking out files with depth two or greater, for instance, you previously needed this:
$ git clone --filter=blob:none --no-checkout /your/repository/here repo
$ cd repo
$ cat >.git/info/sparse-checkout <<EOF
/*
!/*
EOF
$ git config core.sparseCheckout 1
$ git checkout .
Git 2.25’s new command removes that friction. The same thing can now be done this way:
$ git clone --filter=blob:none /your/repository/here repo $ cd repo && git sparse-checkout init
The git sparse-checkout command handles four operations: set to define the list of paths to check out, list to show the current list, and enable/disable to turn sparse checkout on or off entirely. Rather than writing raw patterns, you can add a new path directly:
$ git sparse-checkout set /path/to/check/out
The tradeoff is performance. With both a very large repository and a very long list of include/exclude patterns, Git can spend notable time computing which paths belong in the working copy.
To address this, the new command introduces cone mode, which you enable with git config core.sparseCheckoutCone. In cone mode, you give up arbitrary .gitignore-style patterns in exchange for a much more restrictive—and faster—syntax: you specify either whole subsets of files or entire subdirectories.
Consider a large repository where you do most of your work in A/B/C. What you want is C fully checked out, with enough of A and B to reach it. In cone mode, that’s expressed simply as git sparse-checkout set A/B/C. The command populates the directory tree precisely, and Git does not need to evaluate many complex patterns. Full cone mode semantics are documented in the git-sparse-checkout man page.
Both the new command and partial clone support remain experimental in 2.25, and many hosting providers, including GitHub, do not yet support these workflows. As with previous releases, expect this functionality to continue evolving in upcoming versions of Git.
Deprecation cleanup for git rebase
The --rebase-merges option replaced --preserve-merges in Git 2.22.0, and that older option was deprecated at the same time. Git 2.25 takes the deprecation further by stripping --preserve-merges from all git rebase help text. If any scripts still call git rebase --preserve-merges, now is the time to update them.
Cover letters with branch descriptions
Git development happens over a mailing list rather than through pull requests, and branch descriptions exist to support that workflow. A branch's description is used to fill the cover letter when sending a patch series, which is handy for sending multiple versions of the same patches. Git 2.25 lets you pull the first paragraph of a branch description into the Subject: header of the cover-letter email with git format-patch --cover-from-description subject.
Conflict styles for git apply --3way
git apply --3way leaves the working tree in a conflict-resolution state when a patch does not apply cleanly. The merge.conflictStyle setting controls how Git formats merge conflicts for resolution. In Git 2.25, the two work together: git apply now honors the configured conflict style when it encounters patches that require merge conflict resolution before applying.
Function detection for Elixir
Git can detect function signatures for features like git <diff|grep> --show-function and --function-context, provided the file type is marked via .gitattributes. That support now covers programs written in the Elixir language.
Pathspecs from a file
Commands such as git add, git commit, and git reset understand pathspecs, and passing many of them through command substitution can blow past argument limits. xargs handles that for git add by simply running the command more than once, but that approach breaks for something like git commit, which cannot be run repeatedly to achieve one commit. The new --pathspec-from-file option accepts pathspecs from a file, allowing scripts to pass as many as needed—for example, git commit --pathspec-from-file=your-pathspecs.
Rename detection fix
Directory-level rename detection, which Git has supported for commits since 2.19, had a subtle bug: detection failed when the contents of a subdirectory moved to the repository's root. That bug is fixed in Git 2.25.
Rewriting git add -i in C
The interactive mode of git add (-i) walks through hunks of changes, asking whether each one should be staged. Since its inception, this command has been backed by Perl. In 2018, work began to rewrite the engine in C, a project that came out of an Outreachy internship. Some remaining changes are needed to make git add -p feature-complete; those features are expected soon.
Better git log --graph
For large repositories with long-running branches, git log --graph output can spill well beyond terminal width. A careful refactoring in Git 2.25 improves and simplifies the ASCII rendering while preserving the structure of history. The visual before-and-after comparisons are worth a look at the commit that introduced the change.
New --format verb for email usernames
The --format option for git log has a new verb, l/L, which prints the part of an email address before the @. The casing controls whether the .mailmap translation(s) are applied. In repositories where everyone shares the same email domain, this can reduce visual noise: git log --format='%h %C(cyan)%al %C(yellow)%s.



