A safer way to stage conflict resolutions
Resolving a merge conflict splits into two jobs: editing the working tree until each conflicted path holds the result you want, then staging those paths so Git records the conflict as resolved. The second step is where commands get loose. git add -u updates every modified tracked path, which during a merge can sweep in local changes unrelated to the conflict — or stage a file whose conflict markers you missed.
Git 2.56 adds git add --resolved, which considers only paths currently unmerged in the index. Before staging anything, it scans unmerged regular files for leftover conflict markers; if any are found, it reports the affected paths and leaves the index untouched. Because git status --short uses its two columns for staged and unstaged changes, a resolved file shows as staged while an unrelated local edit stays unstaged.
$ git add --resolved
fatal: the following paths still have conflict markers:
recipe.txt
$ # Edit recipe.txt and remove the conflict markers.
$ git add --resolved
$ git status --short
M notes.txt
M recipe.txt
A pathspec narrows which unmerged paths are considered, and the marker check stays all-or-nothing within that selection: one file with markers means Git stages none of them. Resolved deletions and binary conflicts carry no textual markers, so they stage normally. The mode is deliberately narrower than git add -u or git add -A — it cannot be combined with either, and it ignores tracked files that were never conflicted.
Merge-base search learns to quit early
Merges, three-dot diffs and host-side pull request comparisons all depend on finding the best common ancestor(s) of two commits. Git walks backward from both tips, effectively painting each side’s reachable commits a different color; commits reached by both are merge-base candidates. One candidate is not always enough, since criss-cross merges can yield multiple merge bases unrelated to each other, so the walk has to continue until Git knows it has them all. The old stopping rule, however, could keep grinding through stale already-common history long after another merge base had become impossible.
Git 2.56 instead tracks how many queued commits remain painted exclusively by each side. Once one exclusive side is exhausted, no new meeting point can appear, so the traversal can stop while still returning every merge base. Additional guards surround the rule, but that is the gist.

The gains are large when old side branches were merged into much longer histories: one real monorepo case dropped from 0.68 seconds to 0.01 seconds, and production evaluations across two large monorepos found many cases roughly 70 times faster in one and an average improvement near 20 times in the other. The series also resolved a long-standing Linux-kernel case — with the default v2 commit-graph, git merge-base --all v4.8 v4.9 went from 167,441 traversal steps and 0.29 seconds to 3,887 steps and 0.01 seconds.
Path-walk repacking sheds two host-side blockers
Repacking normally hunts for similar objects that can be stored cheaply as deltas, grouping candidates by name hash. Path-walk repacking visits objects by tree location instead, so versions of the same path sit together and delta relationships are often better. The storage difference is sizable: in a benchmark against a recent clone of the Fluent UI repository with delta recomputation forced, an ordinary bitmapped repack produced a 558.5 MB pack, while --path-walk produced 164.4 MB, about 71% smaller.
Hosts need more than small packs, though. They rely on reachability bitmaps for fast object enumeration, and some use delta islands to keep objects in one ref group from depending on objects available only in another. Path-walk repacking was incompatible with both, which capped where the savings could be used at all.
Git 2.56 lifts both restrictions. A path-walk repack can now select commits for a new bitmap, and later git pack-objects runs can reuse an existing bitmap when it answers the request, falling back to the path walk only when needed. Path-walk additionally performs the bookkeeping delta islands require, propagating island membership through commits and trees before delta bases are chosen.
Nothing here turns path-walk repacking on by default. The point is that two adoption blockers are gone, letting large hosts evaluate the smaller on-disk representation without sacrificing bitmap-assisted serving or delta-island isolation.
Command-line refinements and history surgery
The experimental git history command gains another verb. Git 2.54 introduced the command with reword and split, and Git 2.55 added fixup; 2.56 adds:
$ git history drop <commit>
The selected commit is removed and its descendants are replayed onto the commit's parent. If HEAD moves, Git updates the index and working tree while preserving unrelated local changes, and it aborts rather than overwrite a local change or conflict while replaying a descendant. The command remains experimental, cannot operate on a history containing merge commits, and cannot drop a root or merge commit.
Two common command-line slips are now recognized. git push origin/main prompts for git push origin main, and git branch --set-upstream-to origin main suggests git branch --set-upstream-to=origin/main. Git verifies that each correction is plausible before offering it rather than guessing indiscriminately.
git log --follow no longer depends on traversal order when tracking a path through non-linear history. The command previously carried a single global "current path", so when different parents renamed the path differently, whichever side was visited first could dictate the rest of the walk. Git 2.56 records the path per parent, which also fixes cases such as subtree merges.
Graph output with multiple roots no longer places an unrelated commit directly beneath a root commit in the same column, which made the two look connected. Such "visual roots" are now indented where needed:
* root of one visible history* unrelated commit
This is on by default for git log --graph. --no-graph-indent restores the old rendering, and log.graphIndent sets a default.
Reference plumbing and bulk branch cleanup
Low-level reference writing, historically spread across git update-ref, git symbolic-ref and other plumbing, continues to consolidate under the git refs toolbox:
git refs create refs/heads/topic <new-value>git refs update refs/heads/topic <new-value> [<old-value>]git refs delete refs/heads/topic [<old-value>]git refs rename refs/heads/old refs/heads/new
Supplying an old value gives updates and deletions compare-and-swap protection. These commands are deliberately low-level: git refs rename moves the ref and its reflog but does not apply the branch configuration adjustments that git branch -m handles.
Pruning local topic branches whose work has landed upstream is now possible in bulk, comparing candidate branches against their configured remote-tracking branches:
$ git branch --delete-merged 'origin/*' 'topic-*' --dry-run
Here origin/* matches branches whose upstream lies under origin, topic-* restricts candidates to local branch names beginning with topic-, and --dry-run prints what would be deleted without deleting it. Without --dry-run, only branches whose tips are reachable from their matching upstreams are removed. Branches checked out in a worktree, branches with missing upstreams and several ambiguous push configurations are skipped, and branch.<name>.deleteMerged = false shields a branch from bulk cleanup.
Bisection, replay and partial clones
git bisect run normally finishes with the culprit checked out until git bisect reset is run. The new --reset-when-found[=<where>] combines the two steps. Its default, original, returns to the commit that was checked out before the bisection started; found clears the bisection state but leaves the culprit in place. The option cannot be used together with --no-checkout.
The experimental git replay command can flatten merge topology with --linearize, replaying commits in a single line and dropping merge commits to match the topology git rebase --no-rebase-merges produces, without touching the working tree. It cannot be combined with --contained or with replaying several branches at once.
Blobs fetched on demand by a partial clone have traditionally stayed on disk indefinitely. Git 2.56 can drop large, recoverable blobs and fall back to the promisor remote:
$ git repack -a --filter=blob:limit=1m --drop-filtered --dry-run
$ git repack -a --filter=blob:limit=1m --drop-filtered
The dry run lists candidates; the real repack removes them locally so that later access fetches them again. This is a manual cleanup mechanism rather than an automatically bounded cache, and only blob:limit filters are supported. Git requires a promisor remote and refuses unsafe cases such as dropping an object referenced by the current index. The work was contributed as a GSoC project by Siddharth Shrimali, with Christian Couder and Siddharth Asthana recorded as mentors.
Removing scaling cliffs
Several internal changes eliminate asymptotic blowups in otherwise ordinary operations. Reftable writes no longer reload redundantly after acquiring the lock, making filesystem-stat calls constant instead of linear in the number of refs. Loading known-new packfiles skips the scan of the existing list before every insertion, removing an O(N²) regression that made a prompt-related command take 4.5 seconds in a repository with 37,815 packs.
Quadratic scans were also removed from tombstone-heavy reftables and from path-limited working-tree diffs, and untracked-file collection is now robustly O(n log n) rather than depending on already-sorted input. Reftable tombstone performance tests fell from roughly 13 seconds to 0.2 seconds. On a Chromium checkout with about 500,000 index entries, one affected git diff went from about eight minutes to 0.07 seconds.



