Commit Graph

17528 Commits

Author SHA1 Message Date
Johannes Schindelin
0ddc9cb074 Merge branch 'optionally-dont-append-atomically-on-windows'
Fix append failure issue under remote directories #2753

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-06-26 08:57:58 +00:00
Johannes Schindelin
fd9dcd2a4d Merge pull request #3293 from pascalmuller/http-support-automatically-sending-client-certificate
http: Add support for enabling automatic sending of SSL client certificate
2026-06-26 08:57:57 +00:00
Johannes Schindelin
3317ff510f Merge pull request #2535 from dscho/schannel-revoke-best-effort
Introduce and use the new "best effort" strategy for Secure Channel revoke checking
2026-06-26 08:57:56 +00:00
孙卓识
8ef18ce019 Add config option windows.appendAtomically
Atomic append on windows is only supported on local disk files, and it may
cause errors in other situations, e.g. network file system. If that is the
case, this config option should be used to turn atomic append off.

Co-Authored-By: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: 孙卓识 <sunzhuoshi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-06-26 08:57:51 +00:00
Pascal Muller
ab581d104d http: optionally send SSL client certificate
This adds support for a new http.sslAutoClientCert config value.

In cURL 7.77 or later the schannel backend does not automatically send
client certificates from the Windows Certificate Store anymore.

This config value is only used if http.sslBackend is set to "schannel",
and can be used to opt in to the old behavior and force cURL to send
client certificates.

This fixes https://github.com/git-for-windows/git/issues/3292

Signed-off-by: Pascal Muller <pascalmuller@gmail.com>
2026-06-26 08:57:51 +00:00
Johannes Schindelin
f74211726e http: use new "best effort" strategy for Secure Channel revoke checking
The native Windows HTTPS backend is based on Secure Channel which lets
the caller decide how to handle revocation checking problems caused by
missing information in the certificate or offline CRL distribution
points.

Unfortunately, cURL chose to handle these problems differently than
OpenSSL by default: while OpenSSL happily ignores those problems
(essentially saying "¯\_(ツ)_/¯"), the Secure Channel backend will error
out instead.

As a remedy, the "no revoke" mode was introduced, which turns off
revocation checking altogether. This is a bit heavy-handed. We support
this via the `http.schannelCheckRevoke` setting.

In https://github.com/curl/curl/pull/4981, we contributed an opt-in
"best effort" strategy that emulates what OpenSSL seems to do.

In Git for Windows, we actually want this to be the default. This patch
makes it so, introducing it as a new value for the
`http.schannelCheckRevoke" setting, which now becmes a tristate: it
accepts the values "false", "true" or "best-effort" (defaulting to the
last one).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-06-26 08:57:51 +00:00
Thomas Braun
3a65af87f0 transport: optionally disable side-band-64k
Since commit 0c499ea60f (send-pack: demultiplex a sideband stream with
status data, 2010-02-05) the send-pack builtin uses the side-band-64k
capability if advertised by the server.

Unfortunately this breaks pushing over the dump git protocol if used
over a network connection.

The detailed reasons for this breakage are (by courtesy of Jeff Preshing,
quoted from https://groups.google.com/d/msg/msysgit/at8D7J-h7mw/eaLujILGUWoJ):

	MinGW wraps Windows sockets in CRT file descriptors in order to
	mimic the functionality of POSIX sockets. This causes msvcrt.dll
	to treat sockets as Installable File System (IFS) handles,
	calling ReadFile, WriteFile, DuplicateHandle and CloseHandle on
	them. This approach works well in simple cases on recent
	versions of Windows, but does not support all usage patterns. In
	particular, using this approach, any attempt to read & write
	concurrently on the same socket (from one or more processes)
	will deadlock in a scenario where the read waits for a response
	from the server which is only invoked after the write. This is
	what send_pack currently attempts to do in the use_sideband
	codepath.

The new config option `sendpack.sideband` allows to override the
side-band-64k capability of the server, and thus makes the dumb git
protocol work.

Other transportation methods like ssh and http/https still benefit from
the sideband channel, therefore the default value of `sendpack.sideband`
is still true.

Signed-off-by: Thomas Braun <thomas.braun@byte-physics.de>
Signed-off-by: Oliver Schneider <oliver@assarbad.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2026-06-26 08:57:51 +00:00
Junio C Hamano
faff5b2eb1 Merge branch 'ps/libgit-in-subdir' into seen
The source files for libgit.a have been moved into a new "lib/"
directory to clean up the top-level directory and clearly separate
library code.

* ps/libgit-in-subdir:
  Move libgit.a sources into separate "lib/" directory
  t/helper: prepare "test-example-tap.c" for introduction of "lib/"
2026-06-25 19:51:57 -07:00
Junio C Hamano
dc2a330582 Merge branch 'hn/branch-push-slip-advice' into seen
"git push origin/main" and "git branch origin main" could both be
an obvious typo, in which case offer the obvious typofix.

* hn/branch-push-slip-advice:
  SQUASH??? use test_grep
  push: suggest <remote> <branch> for a slash slip
  branch: suggest <remote>/<branch> on upstream slip
2026-06-25 19:49:56 -07:00
Junio C Hamano
c192528ef5 Merge branch 'hn/history-squash' into seen
The experimental "git history" command has been taught a new
"squash" subcommand to fold a range of commits into a single commit,
replaying any descendants on top.

* hn/history-squash:
  history: re-edit a squash with every message
  history: add squash subcommand to fold a range
  history: give commit_tree_ext a message template
  history: extract helper for a commit's parent tree
2026-06-25 19:49:54 -07:00
Junio C Hamano
1f79c20930 Merge branch 'mm/line-log-limited-ops' into seen
"git log -L<range>:<path>" learned to limit various "diff" operations
like --stat, --check, -G, to the specified range:path.

* mm/line-log-limited-ops:
  diffcore-pickaxe: scope -G to the -L tracked range
  diff: support --check with -L line ranges
  line-log: support diff stat formats with -L
  diff: extract a line-range diff helper for reuse
  diff: emit -L hunk headers via xdiff's formatter
  diff: simplify the line-range filter by classifying removals immediately
  diff: rename and group the line-range filter for clarity
2026-06-25 19:49:54 -07:00
Junio C Hamano
4101c1091e Merge branch 'mm/diff-process-hunks' into seen
A new `diff.<driver>.process` configuration has been introduced to
allow a long-running external process to act as a hunk provider to
allows external tools to control which lines Git considers changed
while leaving all output formatting (word diff, color, blame, etc.) to
Git's standard pipeline.

* mm/diff-process-hunks:
  blame: consult diff process for no-hunk detection
  diff: bypass diff process with --no-ext-diff and in format-patch
  diff: add long-running diff process via diff.<driver>.process
  sub-process: separate process lifecycle from hashmap management
  userdiff: add diff.<driver>.process config
  xdiff: support external hunks via xpparam_t
2026-06-25 19:49:52 -07:00
Junio C Hamano
09829df655 Merge branch 'wy/doc-myfirstcontribution-trim-quotes' into seen
The contributor guide has been updated to advise new contributors to
trim irrelevant quoted text when replying to review comments, matching
the existing advice given to reviewers.

* wy/doc-myfirstcontribution-trim-quotes:
  MyFirstContribution: mention trimming quoted text in replies
2026-06-25 19:49:51 -07:00
Junio C Hamano
d90c822705 Merge branch 'tc/replay-linearize' into seen
git replay learns --linearize option to drop merge commits and
linearize the replayed history, mimicking git rebase
--no-rebase-merges.

* tc/replay-linearize:
  replay: offer an option to linearize the commit topology
  replay: add helper to put entry into mapped_commits
  replay: refactor enum replay_mode into a bool
2026-06-25 19:49:50 -07:00
Junio C Hamano
2120b477f4 Merge branch 'hn/branch-delete-merged' into seen
"git branch" command learned "--delete-merged" option to remove
local branches that have already been merged to the remote-tracking
branches they track.

* hn/branch-delete-merged:
  branch: add --dry-run for --delete-merged
  branch: add branch.<name>.deleteMerged opt-out
  branch: add --delete-merged <branch>
  branch: prepare delete_branches for a bulk caller
  branch: let delete_branches skip unmerged branches on bulk refusal
  branch: convert delete_branches() to a flags argument
  branch: add --forked filter for --list mode
2026-06-25 19:49:49 -07:00
Junio C Hamano
a664703d88 Merge branch 'ps/cat-file-remote-object-info' into seen
The `remote-object-info` command has been added to `git cat-file
--batch-command`, allowing clients to request object metadata
(currently size) from a remote server via protocol v2 without
downloading the entire object.

The client dynamically filters format placeholders based on
server-advertised capabilities and safely returns empty strings for
inapplicable or unsupported fields.

* ps/cat-file-remote-object-info:
  cat-file: make remote-object-info allow-list dynamic
  cat-file: validate remote atoms with allow_list
  cat-file: add remote-object-info to batch-command
  transport: add client support for object-info
  serve: advertise object-info feature
  fetch-pack: move fetch initialization
  connect: refactor packet writing
  fetch-pack: move function to connect.c
  fetch-pack: prepare function to be moved
  t1006: split test utility functions into new "lib-cat-file.sh"
  cat-file: declare loop counter inside for()
  git-compat-util: add strtoul_szt() with error handling
  transport-helper: fix memory leak of helper on disconnect
2026-06-25 19:49:48 -07:00
Junio C Hamano
da665bafc9 Merge branch 'ps/history-drop' into seen
The experimental "git history" command has been taught a new "drop"
subcommand to remove a commit and replay its descendants onto its
parent.

* ps/history-drop:
  builtin/history: implement "drop" subcommand
  builtin/history: split handling of ref updates into two phases
  reset: stop assuming that the caller passes in a clean index
  reset: allow the caller to specify the current HEAD object
  reset: introduce ability to skip updating HEAD
  reset: introduce dry-run mode
  reset: modernize flags passed to `reset_working_tree()`
  reset: rename `reset_head()`
  reset: drop `USE_THE_REPOSITORY_VARIABLE`
  read-cache: split out function to drop unmerged entries to stage 0
2026-06-25 19:49:47 -07:00
Junio C Hamano
bd2e9056ec Merge branch 'ec/commit-fixup-options' into seen
The -m/-F/-c/-C options to supply commit log message from outside the
editor are now supported for all "git commit --fixup" variations.

* ec/commit-fixup-options:
  commit: allow -c/-C for all kinds of --fixup
  commit: allow -m/-F for all kinds of --fixup
2026-06-25 19:49:45 -07:00
Junio C Hamano
ccc0ae563c Merge branch 'cl/conditional-config-on-worktree-path' into seen
The [includeIf "condition"] conditional inclusion facility for
configuration files has learned to use the location of worktree
in its condition.

* cl/conditional-config-on-worktree-path:
  config: add "worktree" and "worktree/i" includeIf conditions
  config: refactor include_by_gitdir() into include_by_path()
2026-06-25 19:49:44 -07:00
Junio C Hamano
c8bbce4f07 Merge branch 'hn/checkout-track-fetch' into seen
"git checkout --track=..." learned to optionally fetch the branch
from the remote the new branch will work with.

* hn/checkout-track-fetch:
  checkout: extend --track with a "fetch" mode to refresh start-point
  branch: expose helpers for finding the remote owning a tracking ref
2026-06-25 19:49:43 -07:00
Junio C Hamano
e08090cc47 Merge branch 'jt/config-lock-timeout' into seen
Configuration file locking now retries for a short period, avoiding
failures when multiple processes attempt to update the configuration
simultaneously.

* jt/config-lock-timeout:
  config: retry acquiring config.lock, configurable via core.configLockTimeout
2026-06-25 19:49:42 -07:00
Junio C Hamano
1740f25d6a Merge branch 'kk/merge-base-exhaustion' into jch
The merge-base computation has been optimized by stopping the walk
early when one side's exclusive commits in the queue are exhausted,
yielding significant speedups for queries with one-sided histories.

* kk/merge-base-exhaustion:
  commit-reach: terminate merge-base walk when one paint side is exhausted
  commit-reach: remove unused nonstale_queue dedup wrappers
  commit-reach: introduce struct paint_state with per-side counters
  commit-reach: add trace2 instrumentation to paint_down_to_common()
  t6099, t6600: add side-exhaustion regression tests
  t6600: add test cases for side-exhaustion edge cases
  Documentation/technical: add paint-down-to-common doc
2026-06-25 19:49:27 -07:00
Junio C Hamano
fe1f339bdd Merge branch 'kh/doc-trailers' into jch
Documentation updates.

* kh/doc-trailers:
  doc: interpret-trailers: document comment line treatment
  doc: interpret-trailers: commit to “trailer block” term
  doc: interpret-trailers: join new-trailers again
  doc: interpret-trailers: add key format example
  doc: interpret-trailers: explain key format
  doc: interpret-trailers: explain the format after the intro
  doc: interpret-trailers: not just for commit messages
  doc: interpret-trailers: use “metadata” in Name as well
  doc: interpret-trailers: replace “lines” with “metadata”
  doc: interpret-trailers: stop fixating on RFC 822
2026-06-25 19:49:25 -07:00
Junio C Hamano
9d3115b852 Merge branch 'kh/doc-replay-config' into jch
Doc update for "git replay" to actually refer to its configuration
variables.

* kh/doc-replay-config:
  doc: replay: move “default” to the right-hand side
  doc: replay: use a nested description list
  doc: replay: improve config description
  doc: link to config for git-replay(1)
2026-06-25 19:49:24 -07:00
Junio C Hamano
1a7d1cf76b Merge branch 'ps/refs-writing-subcommands' into jch
The "git refs" toolbox has been extended with new "create", "delete",
"update", and "rename" subcommands to create, delete, update, and
rename references, respectively.

* ps/refs-writing-subcommands:
  builtin/refs: add "rename" subcommand
  builtin/refs: add "create" subcommand
  builtin/refs: add "update" subcommand
  builtin/refs: add "delete" subcommand
  builtin/refs: drop `the_repository`
2026-06-25 19:49:23 -07:00
Junio C Hamano
6a17da1920 Merge branch 'wy/doc-clarify-review-replies' into jch
Documentation on community contribution guidelines has been updated to
encourage replying to review comments before rerolling, and to advise
a default limit of at most one reroll per day to give reviewers across
different time zones enough time to participate.

* wy/doc-clarify-review-replies:
  doc: advise batching patch rerolls
  doc: encourage review replies before rerolling
2026-06-25 19:49:21 -07:00
Junio C Hamano
8fa129e837 Merge branch 'jk/repo-info-path-keys' into jch
The "git repo info" command has been taught new keys to output both
absolute and relative paths for "gitdir" and "commondir", supported by
a new path-formatting helper extracted from "git rev-parse".

* jk/repo-info-path-keys:
  repo: add path.gitdir with absolute and relative suffix formatting
  repo: add path.commondir with absolute and relative suffix formatting
  path: extract format_path() and use in rev-parse
2026-06-25 19:49:21 -07:00
Junio C Hamano
a72f7d1d95 Merge branch 'mv/log-follow-mergy' into jch
"git log --follow" has been updated to handle non-linear history, in
which the path being tracked gets renamed differently in multiple
history lines, better.

* mv/log-follow-mergy:
  log: improve --follow following renames for non-linear history
2026-06-25 19:49:20 -07:00
Junio C Hamano
8811ac8af4 Merge branch 'tb/pack-path-walk-bitmap-delta-islands' into jch
The pack-objects command now supports using reachability bitmaps and
delta-islands concurrently with the `--path-walk` option, allowing
faster packaging by falling back to path-walk when bitmaps cannot
fully satisfy the request.

* tb/pack-path-walk-bitmap-delta-islands:
  pack-objects: support `--delta-islands` with `--path-walk`
  pack-objects: extract `record_tree_depth()` helper
  pack-objects: support reachability bitmaps with `--path-walk`
  t/perf: drop p5311's lookup-table permutation
2026-06-25 19:49:19 -07:00
Junio C Hamano
c5f1ce3a6d Merge branch 'jc/submittingpatches-design-critiques' into jch
The documentation in SubmittingPatches has been updated to clarify how
patch contributors should respond to design and viability critiques,
and how the resolution of such critiques should be recorded in the
final commit messages.

* jc/submittingpatches-design-critiques:
  SubmittingPatches: address design critiques
2026-06-25 19:49:19 -07:00
Junio C Hamano
302f40deab Merge branch 'kh/submittingpatches-trailers' into jch
The trailer sections in SubmittingPatches have been updated to
encourage use of standard trailers.

* kh/submittingpatches-trailers:
  SubmittingPatches: note that trailer order matters
  SubmittingPatches: be consistent with trailer markup
  SubmittingPatches: document Based-on-patch-by trailer
  SubmittingPatches: discourage common Linux trailers
  SubmittingPatches: encourage trailer use for substantial help
2026-06-25 19:49:19 -07:00
Junio C Hamano
f0291086bc Merge branch 'mh/fetch-follow-remote-head-config' into jch
The `fetch.followRemoteHEAD` configuration variable has been added to
provide a default for the per-remote `remote.<name>.followRemoteHEAD`
setting.

* mh/fetch-follow-remote-head-config:
  fetch: fixup a misaligned comment
  fetch: add configuration variable fetch.followRemoteHEAD
  fetch: refactor do_fetch handling of followRemoteHEAD
  fetch: return 0 on known git_fetch_config
  fetch: rename function report_set_head
  t5510: cleanup remote in followRemoteHEAD dangling ref test
  doc: explain fetchRemoteHEADWarn advice
  fetch: fixup set_head advice for warn-if-not-branch
2026-06-25 19:49:18 -07:00
Junio C Hamano
0feb7b02fe Merge branch 'ps/doc-recommend-b4' into jch
Project-specific configuration for b4 has been introduced, and the
documentation has been updated to recommend using it as a
streamlined method for submitting patches.

* ps/doc-recommend-b4:
  b4: introduce configuration for the Git project
  MyFirstContribution: recommend the use of b4
  MyFirstContribution: recommend shallow threading of cover letters
2026-06-25 19:49:15 -07:00
Junio C Hamano
761e4821bd Merge branch 'cc/promisor-auto-config-url-more' into jch
The handling of promisor-remote protocol capability has been
loosened to allow the other side to add to the list of promisor
remotes via the promisor.acceptFromServerURL configuration
variable.

* cc/promisor-auto-config-url-more:
  doc: promisor: improve acceptFromServer entry
  promisor-remote: auto-configure unknown remotes
  promisor-remote: trust known remotes matching acceptFromServerUrl
  promisor-remote: introduce promisor.acceptFromServerUrl
  promisor-remote: add 'local_name' to 'struct promisor_info'
  urlmatch: add url_normalize_pattern() helper
  urlmatch: change 'allow_globs' arg to bool
  t5710: simplify 'mkdir X' followed by 'git -C X init'
2026-06-25 19:49:13 -07:00
Pablo Sabater
8cdf01a420 cat-file: validate remote atoms with allow_list
strstr() is not enough to validate the format placeholders in
remote-object-info causing two errors:

- Atoms recognized by expand_atom() but the remote doesn't returns 1, but
  data->type contains garbage causing segfault.
- expand_atom() returns 0 for unknown atoms, calling
  strbuf_expand_bad_format() which ends in die() blocking local queries
  if the same format is shared.

Add an allow_list with the supported atoms at the top of expand_atom().
In remote mode, unsupported atoms return 1 leaving the sb empty,
honoring how for-each-ref handles known but inapplicable atoms.

As extra safety, initialize data->type to OBJ_BAD and add a NULL check
for type_name() so uninitialized data doesn't cause segfault.

Update tests that expect previous die() behaviour to expect an empty
string and add an explicit test for empty string return on unknown
placeholder.

Update caveat behaviour documentation.

Mentored-by: Karthik Nayak <karthik.188@gmail.com>
Mentored-by: Chandra Pratap <chandrapratap3519@gmail.com>
Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-25 13:21:14 -07:00
Eric Ju
1b2b551b5e cat-file: add remote-object-info to batch-command
Since the `info` command in `cat-file --batch-command` prints object
info for a given object, it is natural to add another command in
`cat-file --batch-command` to print object info for a given object
from a remote.

Add `remote-object-info` to `cat-file --batch-command`.

While `info` takes object ids one at a time, this creates
overhead when making requests to a server. So `remote-object-info`
instead can take multiple object ids at once.

The `cat-file --batch-command` command is generally implemented in
the following manner:

 - Receive and parse input from user
 - Call respective function attached to command
 - Get object info, print object info

In --buffer mode, this changes to:

 - Receive and parse input from user
 - Store respective function attached to command in a queue
 - After flush, loop through commands in queue
    - Call respective function attached to command
    - Get object info, print object info

Notice how the getting and printing of object info is accomplished one
at a time. As described above, this creates a problem for making
requests to a server. Therefore, `remote-object-info` is implemented in
the following manner:

 - Receive and parse input from user
 If command is `remote-object-info`:
    - Get object info from remote
    - Loop through and print each object info
 Else:
    - Call respective function attached to command
    - Parse input, get object info, print object info

And finally for --buffer mode `remote-object-info`:
 - Receive and parse input from user
 - Store respective function attached to command in a queue
 - After flush, loop through commands in queue:
    If command is `remote-object-info`:
        - Get object info from remote
        - Loop through and print each object info
    Else:
        - Call respective function attached to command
        - Get object info, print object info

To summarize, `remote-object-info` gets object info from the remote and
then loops through the object info passed in, printing the info.

In order for `remote-object-info` to avoid remote communication
overhead in the non-buffer mode, the objects are passed in as such:

remote-object-info <remote> <oid> <oid> ... <oid>

rather than

remote-object-info <remote> <oid>
remote-object-info <remote> <oid>
...
remote-object-info <remote> <oid>

Helped-by: Jonathan Tan <jonathantanmy@google.com>
Helped-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Calvin Wan <calvinwan@google.com>
Signed-off-by: Eric Ju <eric.peijian@gmail.com>
Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-25 13:21:14 -07:00
Harald Nordgren
39c960270d push: suggest <remote> <branch> for a slash slip
When pushing the 'main' branch to the remote 'origin', i.e.,

    $ git push origin main

it is easy to mistakenly write

    $ git push origin/main

That is parsed as the repository to push to, and since 'origin/main'
is neither a configured remote nor a path it dies with:

    fatal: 'origin/main' does not appear to be a git repository

Often 'origin/main' does not exist as a repository, so the command
fails without doing any harm, but it gives no hint that a space was
meant instead of a slash and can leave the user puzzled.

When the argument is not an existing path or configured remote but
its part before the first slash names one, suggest the intended
'<remote> <branch>' form:

    $ git push origin main

The suggestion is shown as advice so it can be silenced with
advice.pushRepoLooksLikeRef.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:21:12 -07:00
Harald Nordgren
4a48af9c27 branch: add --dry-run for --delete-merged
With --dry-run, --delete-merged prints the local branches it would
delete, one "Would delete branch <name>" line each, and exits
without touching any ref. The same filtering applies, so the output
is exactly the set that the real run would delete.

--dry-run is only meaningful together with --delete-merged and is
rejected otherwise.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:18:16 -07:00
Harald Nordgren
365384b1db branch: add branch.<name>.deleteMerged opt-out
Setting branch.<name>.deleteMerged=false exempts that branch from
"git branch --delete-merged", which is useful for a topic you want
to keep developing after an early round of it has been merged
upstream. Unless --quiet is given, each skip is reported so the
user knows why their topic was kept.

Explicit deletion with "git branch -d" still uses the normal merge
check and ignores this setting.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:18:15 -07:00
Harald Nordgren
7b6e901ec8 branch: add --delete-merged <branch>
git branch --delete-merged <branch>...

deletes the local branches that "--forked <branch>" would list,
keeping only those whose tip is reachable from their configured
upstream. The work has already landed on the upstream they track,
so the local copy is no longer needed.

A branch is not deleted when:

  * it is checked out in any worktree
  * its upstream remote-tracking branch no longer exists, since a
    missing upstream is not by itself a sign of integration
  * its push destination equals its upstream (<branch>@{push} is
    the same as <branch>@{upstream}), such as a local "main" that
    tracks and pushes to "origin/main". Right after a pull it just
    looks "fully merged", so it is kept. Only branches that push
    somewhere other than their upstream, typically topics in a fork
    workflow, are candidates.

A branch whose work is not yet merged into its upstream is silently
skipped, so one unmerged topic does not abort the whole sweep.

A branch that another, surviving branch tracks as its upstream is
also kept, so a branch is never deleted out from under one stacked
on top of it. Such a kept branch is itself merged, so when its own
upstream is being deleted, clear its now-stale upstream config.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:18:03 -07:00
Harald Nordgren
82a974308c branch: add --forked filter for --list mode
Add a --forked option to "git branch" list mode that lists only
branches whose configured upstream matches <branch>. The argument
can be a ref (e.g. "origin/main", "master"), a remote name like
"origin" for the branch its origin/HEAD points at, or a shell glob
(e.g. "origin/*"), and may be repeated to widen the filter.

It is an ordinary list filter, so it combines with the others:

    git branch --merged origin/main --forked 'origin/*'

lists branches forked from origin that are already merged into
origin/main, and --no-merged inverts the question.

This is the building block for --delete-merged, which deletes the
listed branches once they have landed on their upstream.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:17:46 -07:00
Harald Nordgren
ec0f5a68cd history: re-edit a squash with every message
By default "git history squash" reuses the oldest commit's message.
When --reedit-message is given it only reopened that one message, so the
messages of the folded-in commits were lost.

Gather the messages of every commit in the range, oldest first, and use
them as the editor template when re-editing, mirroring how "git rebase
-i" presents a squash. The combined message is built before the
descendant walk so it is not disturbed by the flags that walk leaves on
the commits.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:15:29 -07:00
Harald Nordgren
f4b9baec7a history: add squash subcommand to fold a range
Folding a series of commits into one required either an interactive
rebase where each commit after the first was hand-edited to "fixup", or
a "git reset --soft" to the merge base followed by "git commit --amend".

Add "git history squash <revision-range>" to do this directly. It folds
every commit in the range into the oldest one, keeping that commit's
message and authorship and taking the tree of the newest commit, so the
range collapses into a single commit. Commits above the range are
replayed on top of the result.

The range is given as <base>..<tip>, so "git history squash @~3.."
folds the three most recent commits and "git history squash @~5..@~2"
squashes an interior range. A merge inside the range is folded like any
other commit, but the range must have a single base, so a range with
more than one entry point is rejected.

The folded commits leave the history, so by default the command refuses
when another ref points at one of them. Use "--update-refs=head" to
rewrite only the current branch and leave those refs untouched.

Inspired-by: Sergey Chernov <serega.morph@gmail.com>
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:15:26 -07:00
Harald Nordgren
8b13e2d194 checkout: extend --track with a "fetch" mode to refresh start-point
Forking from an existing remote branch without refreshing first often
has consequences: you start work that has already been done, or you
build on an old version of the code which causes big conflicts later
when you pull. The workaround is two commands ("git fetch <remote>
<branch> && git checkout -b <topic> <remote>/<branch>"), and when
the fetch is skipped the checkout silently starts from a stale tip.

Users may already expect "<remote>/<branch>" to refer to the latest
tip on the remote. While this blurs the line between fetch and
checkout, git already does this in places where it pays off: "git
clone" fetches and checks out, and "git pull" fetches and merges.

Add a "fetch" mode to "--track" that refreshes <start-point> before
checking it out:

    git checkout -b new_branch --track=fetch origin/some-branch

Only the requested branch is fetched so other remote-tracking
branches are left untouched. When <start-point> is a bare <remote>
(e.g. "origin"), follow refs/remotes/<remote>/HEAD to learn which
branch to refresh. If "git fetch" fails but the remote-tracking ref
already exists locally, warn and proceed from the existing tip,
otherwise abort.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 15:06:02 -07:00
Kristofer Karlsson
290729c083 commit-reach: terminate merge-base walk when one paint side is exhausted
Add an early termination check to paint_down_to_common() using the
per-side counters introduced earlier. Once the walk enters the
finite-generation region, terminate early when one side's exclusive
count drops to zero -- no new merge-base can form without both paint
sides meeting.

The check also waits for pending_merge_bases to reach zero, ensuring
all merge-base candidates have been dequeued and recorded before
exiting.

The INFINITY gate ensures correctness: commits without a commit-graph
entry have GENERATION_NUMBER_INFINITY and are ordered by commit date,
which is not topologically reliable. The optimization only fires
once the walk enters the finite-generation region where ordering
guarantees hold.

Step counts measured with trace2 on git.git with commit-graph:

  merge-base --all v2.0.0 v2.55.0-rc1:
    before: 72264 steps    after: 44589 steps

  merge-base --all v2.55.0-rc1 v2.55.0-rc1~5:
    before:   110 steps    after:     7 steps

Helped-by: Derrick Stolee <stolee@gmail.com>
Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 09:58:50 -07:00
Kristofer Karlsson
bafb80850a commit-reach: introduce struct paint_state with per-side counters
Add a paint_state struct for use by paint_down_to_common() that
wraps a prio_queue with per-side commit counters. Each non-stale
queued commit occupies exactly one counter bucket based on its
paint flags: PARENT1-only, PARENT2-only, or both sides (a pending
merge-base candidate).

The counters are maintained by paint_count_update() which adjusts
the appropriate bucket by a signed delta. An exhaustive switch on
the paint+stale bits documents all valid flag combinations in one
place.

Convert paint_down_to_common() to use paint_state. The loop now
drains the queue via paint_queue_get() which returns NULL when all
counters reach zero, replacing the old pointer-based termination
(max_nonstale). This is equivalent behavior -- both conditions
detect that no non-stale entries remain.

The existing nonstale_queue is left in place for ahead_behind().

Step counts (via trace2 from the previous commit) are identical
before and after this refactoring, confirming no behavioral change.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 09:58:50 -07:00
Kristofer Karlsson
6aaf850263 Documentation/technical: add paint-down-to-common doc
Add a technical document describing the paint_down_to_common()
algorithm used for merge-base computation, covering the paint
walk, generation number regions, and termination conditions.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-24 09:58:50 -07:00
K Jayatheerth
3ac28d832a repo: add path.gitdir with absolute and relative suffix formatting
Scripts need a stable way to locate the git directory without
parsing rev-parse output or relying on its flag-driven path format
selection. There is no way to retrieve this path from git repo info
today.

Introduce path.gitdir.absolute and path.gitdir.relative keys,
consistent with the path.commondir keys added in the previous patch.
Reuse the test_repo_info_path helper introduced there to validate
both variants.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-23 21:15:52 -07:00
K Jayatheerth
1efca6d0b2 repo: add path.commondir with absolute and relative suffix formatting
Scripts working with worktree setups need a reliable way to discover
the common directory, which diverges from the git directory when
multiple worktrees are in use. There is no way to retrieve this path
from git repo info today.

Introduce path.commondir.absolute and path.commondir.relative keys.
Exposing explicit format variants rather than a single key with a
default avoids ambiguity for scripts that require predictable output.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-23 21:15:52 -07:00
Junio C Hamano
ab776a62a7 Git 2.55-rc2
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-22 20:05:04 -07:00