]> git.ipfire.org Git - thirdparty/git.git/log
thirdparty/git.git
30 hours agoMerge branch 'master' of https://github.com/j6t/git-gui main master
Junio C Hamano [Fri, 12 Jun 2026 12:41:40 +0000 (05:41 -0700)] 
Merge branch 'master' of https://github.com/j6t/git-gui

* 'master' of https://github.com/j6t/git-gui:
  git-gui: silence install recipes under "make -s"
  git-gui: add gui and pick as explicit subcommands
  git-gui: check browser/blame arguments carefully
  git-gui: allow specifying path '.' to the browser
  git-gui: try harder to find worktree from gitdir
  git-gui: simplify [is_bare] to report if a worktree is known
  git-gui: use git rev-parse for worktree discovery
  git-gui: use rev-parse exclusively to find a repository
  git-gui: use --absolute-git-dir
  git-gui: do not change global vars in choose_repository::pick
  git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE
  git-gui: remove unnecessary 'cd $_gitworktree' from do_gitk
  git-gui: use HEAD as current branch when detached

30 hours agoMerge branch 'master' of https://github.com/j6t/gitk
Junio C Hamano [Fri, 12 Jun 2026 12:40:38 +0000 (05:40 -0700)] 
Merge branch 'master' of https://github.com/j6t/gitk

* 'master' of https://github.com/j6t/gitk:
  gitk: add horizontal scrollbar to the commit list pane

34 hours agoMerge branch 'horizontal-scroll' of github.com:ramcdona/gitk
Johannes Sixt [Fri, 12 Jun 2026 09:30:22 +0000 (11:30 +0200)] 
Merge branch 'horizontal-scroll' of github.com:ramcdona/gitk

* 'horizontal-scroll' of github.com:ramcdona/gitk:
  gitk: add horizontal scrollbar to the commit list pane

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
34 hours agoMerge branch 'ml/repo-discovery'
Johannes Sixt [Fri, 12 Jun 2026 09:05:28 +0000 (11:05 +0200)] 
Merge branch 'ml/repo-discovery'

* ml/repo-discovery:
  git-gui: add gui and pick as explicit subcommands
  git-gui: check browser/blame arguments carefully
  git-gui: allow specifying path '.' to the browser
  git-gui: try harder to find worktree from gitdir
  git-gui: simplify [is_bare] to report if a worktree is known
  git-gui: use git rev-parse for worktree discovery
  git-gui: use rev-parse exclusively to find a repository
  git-gui: use --absolute-git-dir
  git-gui: do not change global vars in choose_repository::pick
  git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE
  git-gui: remove unnecessary 'cd $_gitworktree' from do_gitk
  git-gui: use HEAD as current branch when detached

2 days agoGit 2.55-rc0 v2.55.0-rc0
Junio C Hamano [Thu, 11 Jun 2026 11:29:59 +0000 (04:29 -0700)] 
Git 2.55-rc0

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 days agoMerge branch 'hn/macos-linker-warning'
Junio C Hamano [Thu, 11 Jun 2026 11:31:19 +0000 (04:31 -0700)] 
Merge branch 'hn/macos-linker-warning'

A linker warning on macOS when building with Xcode 16.3 or newer has
been avoided by passing -fno-common to the compiler when a
sufficiently new linker is detected.

* hn/macos-linker-warning:
  config.mak.uname: avoid macOS linker warning on Xcode 16.3+

2 days agoMerge branch 'kk/wildmatch-windows-ls-files-prereq'
Junio C Hamano [Thu, 11 Jun 2026 11:31:19 +0000 (04:31 -0700)] 
Merge branch 'kk/wildmatch-windows-ls-files-prereq'

In t3070-wildmatch, "via ls-files" test variants with patterns
containing backslash escapes are now skipped on Windows, avoiding 36
test failures caused by pathspec separator conversion.

* kk/wildmatch-windows-ls-files-prereq:
  t3070: skip ls-files tests with backslash patterns on Windows

2 days agoMerge branch 'mm/doc-word-diff'
Junio C Hamano [Thu, 11 Jun 2026 11:31:18 +0000 (04:31 -0700)] 
Merge branch 'mm/doc-word-diff'

The documentation for "--word-diff" has been extended with a bit of
implementation detail of where these different words come from.

* mm/doc-word-diff:
  doc: clarify that --word-diff operates on line-level hunks

2 days agoMerge branch 'lp/http-fetch-pack-index-leak-fix'
Junio C Hamano [Thu, 11 Jun 2026 11:31:18 +0000 (04:31 -0700)] 
Merge branch 'lp/http-fetch-pack-index-leak-fix'

A memory leak in `fetch_and_setup_pack_index()` when verification of
the downloaded pack index fails has been plugged. Also an obsolete
`unlink()` call on parse failure has been cleaned up.

* lp/http-fetch-pack-index-leak-fix:
  http: fix memory leak in fetch_and_setup_pack_index()
  http: cleanup function fetch_and_setup_pack_index()

2 days agoMerge branch 'ps/odb-source-loose'
Junio C Hamano [Thu, 11 Jun 2026 11:31:18 +0000 (04:31 -0700)] 
Merge branch 'ps/odb-source-loose'

The loose object source has been refactored into a proper `struct
odb_source`.

* ps/odb-source-loose:
  odb/source-loose: drop pointer to the "files" source
  odb/source-loose: stub out remaining callbacks
  odb/source-loose: wire up `write_object_stream()` callback
  object-file: refactor writing objects to use loose source
  odb/source-loose: wire up `write_object()` callback
  loose: refactor object map to operate on `struct odb_source_loose`
  odb/source-loose: wire up `freshen_object()` callback
  odb/source-loose: drop `odb_source_loose_has_object()`
  odb/source-loose: wire up `count_objects()` callback
  odb/source-loose: wire up `find_abbrev_len()` callback
  odb/source-loose: wire up `for_each_object()` callback
  odb/source-loose: wire up `read_object_stream()` callback
  odb/source-loose: wire up `read_object_info()` callback
  odb/source-loose: wire up `close()` callback
  odb/source-loose: wire up `reprepare()` callback
  odb/source-loose: start converting to a proper `struct odb_source`
  odb/source-loose: store pointer to "files" instead of generic source
  odb/source-loose: move loose source into "odb/" subsystem

2 days agoMerge branch 'mm/line-log-cleanup'
Junio C Hamano [Thu, 11 Jun 2026 11:31:17 +0000 (04:31 -0700)] 
Merge branch 'mm/line-log-cleanup'

The `git log -L` implementation has been refactored to use the
standard diff output pipeline, enabling pickaxe and diff-filter to
work as expected. Additionally, metadata-only diff formats like
--raw and --name-only are now supported with -L.

* mm/line-log-cleanup:
  line-log: allow non-patch diff formats with -L
  line-log: integrate -L output with the standard log-tree pipeline
  revision: move -L setup before output_format-to-diff derivation

2 days agoMerge branch 'st/daemon-sockaddr-fixes'
Junio C Hamano [Thu, 11 Jun 2026 11:31:17 +0000 (04:31 -0700)] 
Merge branch 'st/daemon-sockaddr-fixes'

Correct use of sockaddr API in "git daemon".

* st/daemon-sockaddr-fixes:
  daemon: guard NULL REMOTE_PORT in execute() logging
  daemon: fix IPv6 address truncation in ip2str()
  daemon: fix IPv6 address corruption in lookup_hostname()

4 days agoThe 13th batch
Junio C Hamano [Tue, 9 Jun 2026 01:04:31 +0000 (10:04 +0900)] 
The 13th batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 days agoMerge branch 'jc/doc-monitor-ghci'
Junio C Hamano [Tue, 9 Jun 2026 01:04:51 +0000 (10:04 +0900)] 
Merge branch 'jc/doc-monitor-ghci'

Encourage original authors to monitor the CI status.

* jc/doc-monitor-ghci:
  SubmittingPatches: proactively monitor GHCI pages

4 days agoMerge branch 'ib/doc-push-default-simple'
Junio C Hamano [Tue, 9 Jun 2026 01:04:51 +0000 (10:04 +0900)] 
Merge branch 'ib/doc-push-default-simple'

The documentation for `push.default = simple` has been clarified to
better explain its behavior, making it clear that it pushes the
current branch to a same-named branch on the remote, and detailing
the upstream requirements for centralized workflows.

* ib/doc-push-default-simple:
  doc: clarify push.default=simple behavior

4 days agoMerge branch 'gh/jump-auto-mode'
Junio C Hamano [Tue, 9 Jun 2026 01:04:50 +0000 (10:04 +0900)] 
Merge branch 'gh/jump-auto-mode'

The 'git-jump' command (in contrib/) has been taught to automatically
pick a mode (merge, diff, or ws) when invoked without arguments.

* gh/jump-auto-mode:
  git-jump: pick a mode automatically when invoked without arguments

4 days agoMerge branch 'rs/strbuf-add-oid-hex'
Junio C Hamano [Tue, 9 Jun 2026 01:04:50 +0000 (10:04 +0900)] 
Merge branch 'rs/strbuf-add-oid-hex'

Formatting object name in full hexadecimal form has been optimized
by using a new strbuf_add_oid_hex() helper function.

* rs/strbuf-add-oid-hex:
  hex: add and use strbuf_add_oid_hex()

4 days agoMerge branch 'rs/strbuf-add-uint'
Junio C Hamano [Tue, 9 Jun 2026 01:04:50 +0000 (10:04 +0900)] 
Merge branch 'rs/strbuf-add-uint'

Adding a decimal integer with strbuf_addf("%u") appears commonly;
they have been optimized by using a custom formatter.

* rs/strbuf-add-uint:
  ls-tree: use strbuf_add_uint()
  ls-files: use strbuf_add_uint()
  cat-file: use strbuf_add_uint()
  strbuf: add strbuf_add_uint()

4 days agoMerge branch 'ua/push-remote-group'
Junio C Hamano [Tue, 9 Jun 2026 01:04:50 +0000 (10:04 +0900)] 
Merge branch 'ua/push-remote-group'

"git push" learned to take a "remote group" name to push to, which
causes pushes to multiple places, just like "git fetch" would do.

* ua/push-remote-group:
  push: support pushing to a remote group
  remote: move remote group resolution to remote.c
  remote: fix sign-compare warnings in push_cas_option

4 days agoMerge branch 'th/promisor-quiet-per-repo'
Junio C Hamano [Tue, 9 Jun 2026 01:04:49 +0000 (10:04 +0900)] 
Merge branch 'th/promisor-quiet-per-repo'

The "promisor.quiet" configuration variable was not used from
relevant submodules when commands like "grep --recurse-submodules"
triggered a lazy fetch, which has been corrected.

* th/promisor-quiet-per-repo:
  promisor-remote: fix promisor.quiet to use the correct repository

4 days agoMerge branch 'tb/bitmap-build-performance'
Junio C Hamano [Tue, 9 Jun 2026 01:04:49 +0000 (10:04 +0900)] 
Merge branch 'tb/bitmap-build-performance'

Reachability bitmap generation has been significantly optimized. By
reordering tree traversal, caching object positions, and refining how
pseudo-merge bitmaps are constructed, the performance of "git repack
--write-midx-bitmaps" is improved, especially for large repositories
and when using pseudo-merges.

* tb/bitmap-build-performance:
  pack-bitmap: build pseudo-merge bitmaps after regular bitmaps
  pack-bitmap: remember pseudo-merge parents
  pack-bitmap: sort bitmaps before XORing
  pack-bitmap: cache object positions during fill
  pack-bitmap: consolidate `find_object_pos()` success path
  pack-bitmap: reuse stored selected bitmaps
  pack-bitmap: check subtree bits before recursing
  pack-bitmap: pass object position to `fill_bitmap_tree()`

6 days agoThe 12th batch
Junio C Hamano [Sun, 7 Jun 2026 14:58:12 +0000 (23:58 +0900)] 
The 12th batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 days agoMerge branch 'ja/doc-synopsis-style-again'
Junio C Hamano [Sun, 7 Jun 2026 14:58:25 +0000 (23:58 +0900)] 
Merge branch 'ja/doc-synopsis-style-again'

A batch of documentation pages has been updated to use the modern
synopsis style.

* ja/doc-synopsis-style-again:
  doc: convert git-imap-send synopsis and options to new style
  doc: convert git-apply synopsis and options to new style
  doc: convert git-am synopsis and options to new style
  doc: convert git-grep synopsis and options to new style
  doc: git bisect: clarify the usage of the synopsis vs actual command
  doc: convert git-bisect to synopsis style

6 days agoMerge branch 'kk/commit-reach-optim'
Junio C Hamano [Sun, 7 Jun 2026 14:58:25 +0000 (23:58 +0900)] 
Merge branch 'kk/commit-reach-optim'

The check for non-stale commits in the priority queue used by
`paint_down_to_common` and `ahead_behind` has been optimized by
replacing an O(N) scan with an O(1) counter, yielding performance
improvements in repositories with wide histories.

* kk/commit-reach-optim:
  commit-reach: replace queue_has_nonstale() scan with O(1) tracking
  commit-reach: deduplicate queue entries in paint_down_to_common
  object.h: fix stale entries in object flag allocation table

6 days agoMerge branch 'aj/stash-patch-optimize-temporary-index'
Junio C Hamano [Sun, 7 Jun 2026 14:58:24 +0000 (23:58 +0900)] 
Merge branch 'aj/stash-patch-optimize-temporary-index'

"git stash -p" has been optimized by reusing cached index
entries in its temporary index, avoiding unnecessary lstat()
calls on unchanged files.

* aj/stash-patch-optimize-temporary-index:
  stash: reuse cached index entries in --patch temporary index

6 days agoMerge branch 'kh/free-commit-list'
Junio C Hamano [Sun, 7 Jun 2026 14:58:24 +0000 (23:58 +0900)] 
Merge branch 'kh/free-commit-list'

Code clean-up.

* kh/free-commit-list:
  commit: remove deprecated functions
  *: replace deprecated free_commit_list

6 days agoMerge branch 'ds/restore-sparse-index'
Junio C Hamano [Sun, 7 Jun 2026 14:58:24 +0000 (23:58 +0900)] 
Merge branch 'ds/restore-sparse-index'

'git restore --staged' has been optimized to avoid unnecessarily expanding
the sparse index when operating on paths within the sparse checkout
definition, by handling sparse directory entries at the tree level.

* ds/restore-sparse-index:
  restore: avoid sparse index expansion
  t1092: test 'git restore' with sparse index

6 days agoMerge branch 'ar/receive-pack-worktree-env'
Junio C Hamano [Sun, 7 Jun 2026 14:58:24 +0000 (23:58 +0900)] 
Merge branch 'ar/receive-pack-worktree-env'

The GIT_WORK_TREE variable prepared to invoke the push-to-checkout
hook was leaking into the environment even when there was no hook
used and broke the default push-to-deploy (i.e., let "git checkout"
update the working tree only when the working tree is clean).

* ar/receive-pack-worktree-env:
  receive-pack: fix updateInstead with core.worktree

7 days agogit-gui: silence install recipes under "make -s"
Harald Nordgren [Thu, 4 Jun 2026 06:48:50 +0000 (06:48 +0000)] 
git-gui: silence install recipes under "make -s"

Several install and uninstall recipes embed "echo" calls that fire as
part of the recipe itself, so the install banners (DEST, INSTALL,
LINK, REMOVE) were visible whenever the variables expand non-empty.

Guard the whole "ifndef V" block on "-s" so the loud variants are
selected only when "-s" is absent and V=1 is unset. The existing
"-s" check also had its findstring arguments in the wrong order
(needle "-s" never fit in haystack "s"), so swap them while moving
the check to wrap the block.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: add gui and pick as explicit subcommands
Mark Levedahl [Sun, 31 May 2026 23:02:25 +0000 (19:02 -0400)] 
git-gui: add gui and pick as explicit subcommands

git-gui accepts subcommands blame | browser | citool, and assumes the
subcommand is 'gui' if none is actually given, But, git-gui also has a
repository picker (choose_repository::pick) that can create a new
repository + worktree, or choose an existing one, switch to that, and
the run the gui. The user has no direct control over invoking the
picker, instead the picker is triggered by failure in the repository /
worktree discovery process: this includes being started in a directory
not controlled by git, which is probably the intended use case.

The picker can appear when the user has no intention of creating a new
worktree, and the user cannot use the picker to create a new worktree
inside another.

So, add two explicit subcommands:
    gui  - Run the gui if repository/worktree discovery succeeds, or die
           with an error message, but never run the picker.
    pick - First run the picker, regardless, then start the gui in
           the chosen worktree.

Nothing in this changes the prior behavior, the alternates above must be
explicitly selected to see any change.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: check browser/blame arguments carefully
Mark Levedahl [Sun, 31 May 2026 23:02:24 +0000 (19:02 -0400)] 
git-gui: check browser/blame arguments carefully

git gui offers two related commands, browser and blame, that provide
graphical interfaces driven by git ls-tree and git blame. As such, the
arguments to git-gui need to satisfy those two git commands. But,
git-gui does not assure this leading to confusing or incorrect results.
For instance 'git browser <non-existent path>' shows a blank browser
window rather than error message.

Also, commit 3e45ee1ef2 ("git-gui: Smarter command line parsing for
browser, blame", 2007-05-08) implemented code to allow giving path
before rev on the command line, and unconditionally uses the worktree to
disambiguate. As a result, the following command run in a current
git-gui checkout of the master branch shows the master branch version of
blame.tcl, when none should be shown as that file does not exist in
gitgui-0.6.0.

  git gui blame lib/blame.tcl gitgui-0.6.0

This 'file before rev' feature in git-gui mirrors ideas considered when
git's user interface was very young, but no such feature is documented
for any git command.  Rather than try to fix an idea git itself
rejected, let's just remove this broken and hopefully unused feature.

git-gui browser|blame both accept 'rev' and 'path' as command line
arguments.  rev defaults to 'HEAD' if not given, while path must be
given. path names a directory tree to ls-tree or a file to blame. path
must exist in rev for ls-tree and for blame.  In addition git blame will
include uncommitted changes from the worktree file at 'path' if rev is
not given (thus defaulting to HEAD), but still requires that the file
exists in HEAD.

So, let's clean up the parser to check that the arguments are usable.
- give a full synopsis, including '--' that may be used to separate rev and
  path. (as path is the required final arg, -- gives no extra info)
- explicitly check the number of arguments
- use rev-parse to assure a user supplied rev is valid
- use ls-tree to assure that path exists in rev
- for blame only, with no rev given and a worktree existing, also assure
  that path points to a file in the worktree

With these changes, error messages are thrown by the parser if the path
or rev are not known: no blank or erroneous displays are created. Also,
this avoids accessing the worktree except in the specific use case
supported by blame / git-blame, meaning browser|blame now also work
without a worktree.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: allow specifying path '.' to the browser
Mark Levedahl [Sun, 31 May 2026 23:02:23 +0000 (19:02 -0400)] 
git-gui: allow specifying path '.' to the browser

Invoking "git-gui browser rev ." should show the file browser for the
commitish rev, starting at the current directory. When the current
directory is the working tree root, this errors out in normalize_relpath
because the '.' is removed, yielding an empty list as argument to [file
join ...]. git ls-tree (underlying the browser) accepts '.', so use that
as the value when in the root.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: try harder to find worktree from gitdir
Mark Levedahl [Sun, 31 May 2026 23:02:22 +0000 (19:02 -0400)] 
git-gui: try harder to find worktree from gitdir

git-gui, since 87cd09f43e ("git-gui: work from the .git dir",
2010-01-23), has had the intent to allow starting from inside a
repository, then switching to the parent directory if that is a valid
worktree.

This certainly hasn't worked since 2d92ab32fd ("rev-parse: make
--show-toplevel without a worktree an error", 2019-11-19) in git, but
breaking this git-gui feature was unintentional.

There are (at least) 3 cases where the gitdir can tell us where the
worktree is, and we would like all to work:

- core.worktree is set, and points to a valid worktree. This is already
  handled  by git rev-parse --show-toplevel, even when not in the worktree.
  There is nothing more to do in this case.

- the gitdir is embedded in a worktree as subdirectory .git. The parent
  is (or at least should be) a valid worktree. This worked long ago.

- the gitdir is a worktree specific directory (under
  <mainrepo>/worktrees/worktree_name), within which there is a file
  "gitdir" pointing to .git in the worktree. git gui never learned to
  handle this case.

Let's handle the latter two cases. Always check that the discovered
worktree is valid and points to the already discovered gitdir according
to git rev-parse. This avoids issues that may arise because we are
discovering from the gitdir up, rather than the worktree down, and file
system non-posix behavior or misconfiguration of git might cause
confusion.  For instance, a manually moved worktree might not be where
the gitdir points, or the gitdir might be configured with
core.bare=true.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: simplify [is_bare] to report if a worktree is known
Mark Levedahl [Sun, 31 May 2026 23:02:21 +0000 (19:02 -0400)] 
git-gui: simplify [is_bare] to report if a worktree is known

git-gui includes proc is_bare, used in several places to make decisions
on whether a worktree exists, but also in discovery to tell if a
worktree can be supported.

But, is_bare is out of date with regard to multiple worktrees, safe
repository guards, and possibly other relevant features known to git
rev-parse. Also, is_bare caches its result on the first call, so is not
useful if a later step in the discovery process finds a worktree.

So, simplify is_bare to report whether git-gui has a worktree or is
working only from a repository.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: use git rev-parse for worktree discovery
Mark Levedahl [Sun, 31 May 2026 23:02:20 +0000 (19:02 -0400)] 
git-gui: use git rev-parse for worktree discovery

git gui uses a combination of tcl code and git invocations to determine
the worktree and the location with respect to the worktree root
(_prefix). But, git rev-parse provides all of this information directly,
and assures full error and configuration checking are done by git
itself. The entirety of discovery in normal configurations involves

git rev-parse --show-toplevel (gets worktree root)
git rev-parse --show-prefix (shows location wrt the root)

An error thrown on either of these lines means the worktree discovered
by git is unusable, or git did not discover a worktree because the
current directory is inside the repository. If the user has defined
GIT_DIR or GIT_WORK_TREE, this is a user configuration error and git-gui
should stop.

Otherwise, the blame or browser subcommands can be used without a
worktree.

A separate error might occur when changing to the root of the discovered
worktree. The cause would be file system related and completely outside
of git's control, so trap that independently.

Discovery of the repository and the worktree must be guarded to trap
errors: the intent is that any configuration problems are caught during
discovery, and later processing need not include error trapping and
recovery. So, move all worktree discovery code to be immediately after
repository discovery.

This does move configuration loading to occur after worktree discovery
rather than before. None of the code executed in worktree discovery has
any option controlled by a git-gui configuration variable, so no impact
is expected. git itself will always read the repository configuration,
including worktree specific configuration data if that exists, so this
is unaffected by when git-gui loads its own config data. Also, we cannot
be sure the worktree dependent configuration can be loaded before
full discovery is complete.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: use rev-parse exclusively to find a repository
Mark Levedahl [Sun, 31 May 2026 23:02:19 +0000 (19:02 -0400)] 
git-gui: use rev-parse exclusively to find a repository

git-gui attempts to use env(GIT_DIR) directly as the git repository,
accepting GIT_DIR if it is a directory. Only if that fails is git
rev-parse used to discover the repository.  But, this avoids all of
git-core's validity checking on a repository, thus possibly deferring an
error to a later step, possibly unexpected. Repository validation should
be part of initial setup so that later processing does not need error
trapping for configuration errors.

Let's just invoke rev-parse so all error checking is done.

While here, let's cleanup the error handling.

Stop if an error occurs and the user set GIT_DIR or GIT_WORK_TREE.
Use of either or both of those variables is supported by git, but their
use also means the user has taken responsibility that they are correct,
so a failure is something the user must address.

Otherwise on error, continue the existing behavior and show the
repository picker. But, let's move the possible invocation of
repository_chooser::pick to a separate code block. This permits adding
separate conditions on using pick independent of repository discovery, and
will be exploited later in the series.  Note that the picker always
returns with the current directory in the root of a worktree with the
git repository is in the .git subdirectory.  The variable "picked" is
used by git-gui to automatically execute the "Explore Working Copy" menu
item after the repository picker is run.  This is controlled by config
variable gui.autoexplore, and happens after all discovery is complete.

Remove a later check on whether _gitdir is a directory: that code
cannot be reached without rev-parse already validating the repository.

_prefix is set as part of worktree discovery, but must be {} if not
running with a worktree. Initialze this as {} along with other global
variables, this is the correct value is no worktree is found.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: use --absolute-git-dir
Mark Levedahl [Sun, 31 May 2026 23:02:18 +0000 (19:02 -0400)] 
git-gui: use --absolute-git-dir

git-gui uses git rev-parse --git-dir to get the pathname of the
discovered git repository. The returned value can be relative, and is
'.' if the current directory is the top of the repository directory
itself.  git-gui has code to change '.' to [pwd] in this case so that
subsequent logic runs.

But, git rev-parse supports --absolute-git-dir from fac60b8925
("rev-parse: add option for absolute or relative path formatting",
2020-12-13), and included in git 2.31. git-gui requires git >= 2.36, so
this more useful form is always available. Use --absolute-git-dir to
always get an absolute path, avoiding the need for other checks, and
delete the now unneeded code to fix a relative _gitdir.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: do not change global vars in choose_repository::pick
Mark Levedahl [Sun, 31 May 2026 23:02:17 +0000 (19:02 -0400)] 
git-gui: do not change global vars in choose_repository::pick

The repository picker (choose_repository::pick, AKA pick) on success
always returns with the current directory at the root of the selected
worktree, with the global variable _gitdir holding the name of the
git repository, possibly as a relative path, and _prefix {}. The
worktree root (_gitworktree) is not filled out, and if the selection was
from the "recent" list, no validation has occurred beyond testing that
the worktree root exists. So, repository and worktree validation are
still needed to be sure the new repo + worktree is usable.

pick only supports worktrees with a .git entry in the worktree root, so
git repository and worktree discovery will work starting in the current
directory on return. In cases of error, or user abort, pick exits the
process rather than returning.

So, let's change pick to not alter any global values, with success
indicated by the process returning to the caller. In this case, the
current directory is the worktree root, with a .git entry. The caller
then proceeds with normal discovery to find and validate both repository
and worktree.

With this, pick now returns 1 in the success case, but additional work
would be necessary to return from conditions where 0 should be returned.
Checking this return value would be superfluous.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agogit-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE
Mark Levedahl [Sun, 31 May 2026 23:02:16 +0000 (19:02 -0400)] 
git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE

git-gui unconditionally exports _gitdir as GIT_DIR, and _gitworktree as
GIT_WORK_TREE, to the environment, and unconditionally
unsets these environment variables before invoking gitk or git-gui when
a submodule is involved. This export happens even if _gitworktree is
empty, which happens when running from a bare repository. However,
exporting GIT_WORK_TREE as empty is never valid, and causes errors in
git.

GIT_DIR must be exported if the repository is not discoverable from the
worktree (or current directory if there is no worktree). The user might
have configured this.

If there is a worktree, git-gui makes this the current directory.
However, if the repository sets core.worktree, this value can only be
overridden by GIT_WORK_TREE so the latter must be exported.

As we cannot eliminate conditions where either variable is needed, let's
implement a pair of functions to set / unset these variables without
error, and without ever exporting an empty GIT_WORK_TREE.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
11 days agoconfig.mak.uname: avoid macOS linker warning on Xcode 16.3+
Harald Nordgren [Tue, 2 Jun 2026 07:37:58 +0000 (07:37 +0000)] 
config.mak.uname: avoid macOS linker warning on Xcode 16.3+

Building on macOS with Xcode 16.3 or newer emits:

    ld: warning: reducing alignment of section __DATA,__common
    from 0x8000 to 0x4000 because it exceeds segment maximum
    alignment

Pass -fno-common when "ld -v" reports ld-1167 or newer, so tentative
definitions of large arrays go into BSS instead of __DATA,__common.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
11 days agoThe 11th batch
Junio C Hamano [Tue, 2 Jun 2026 03:48:59 +0000 (12:48 +0900)] 
The 11th batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
11 days agoMerge branch 'kh/doc-hook'
Junio C Hamano [Tue, 2 Jun 2026 07:15:29 +0000 (16:15 +0900)] 
Merge branch 'kh/doc-hook'

Doc updates.

* kh/doc-hook:
  doc: hook: don’t self-link via config include
  doc: config: include existing git-hook(1) section
  doc: hook: consistently capitalize Git
  doc: hook: remove stray backtick

11 days agoMerge branch 'ds/path-walk-filters'
Junio C Hamano [Tue, 2 Jun 2026 07:15:29 +0000 (16:15 +0900)] 
Merge branch 'ds/path-walk-filters'

The "git pack-objects --path-walk" traversal has been integrated
with several object filters, including blobless and sparse filters.

* ds/path-walk-filters:
  path-walk: support `combine` filter
  path-walk: support `object:type` filter
  path-walk: support `tree:0` filter
  t6601: tag otherwise-unreachable trees
  pack-objects: support sparse:oid filter with path-walk
  path-walk: add pl_sparse_trees to control tree pruning
  path-walk: support blob size limit filter
  backfill: die on incompatible filter options
  path-walk: support blobless filter
  path-walk: always emit directly-requested objects
  t/perf: add pack-objects filter and path-walk benchmark
  pack-objects: pass --objects with --path-walk
  t5620: make test work with path-walk var

11 days agoMerge branch 'ta/approxidate-noon-fix'
Junio C Hamano [Tue, 2 Jun 2026 07:15:29 +0000 (16:15 +0900)] 
Merge branch 'ta/approxidate-noon-fix'

"Friday noon" asked in the morning on Sunday was parsed to be one
day before the specified time, which has been corrected.

* ta/approxidate-noon-fix:
  approxidate: use deferred mday adjustments for "specials"
  approxidate: make "specials" respect fixed day-of-month
  t0006: add support for approxidate test date adjustment
  approxidate: make "today" wrap to midnight

11 days agoMerge branch 'jk/connect-service-enum'
Junio C Hamano [Tue, 2 Jun 2026 07:15:28 +0000 (16:15 +0900)] 
Merge branch 'jk/connect-service-enum'

The "name" argument in git_connect() and related functions has been
converted to a "service" enum to improve type safety and clarify its
purpose.

* jk/connect-service-enum:
  transport-helper: fix typo in BUG() message
  connect: use "service" enum for "name" argument

11 days agohttp: fix memory leak in fetch_and_setup_pack_index()
LorenzoPegorari [Mon, 1 Jun 2026 13:52:12 +0000 (15:52 +0200)] 
http: fix memory leak in fetch_and_setup_pack_index()

Inside the function `fetch_and_setup_pack_index()`, when the pack
obtained using `parse_pack_index()` fails to be verified by
`verify_pack_index()`, the function returns without closing and freeing
said pack.

Fix this by calling `close_pack_index()` to munmap the index file for
the leaking pack (which might have been mmapped by `fetch_pack_index()`
or `verify_pack_index()`), and then free it, when the verification
fails.

Signed-off-by: LorenzoPegorari <lorenzo.pegorari2002@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
11 days agohttp: cleanup function fetch_and_setup_pack_index()
LorenzoPegorari [Mon, 1 Jun 2026 13:52:01 +0000 (15:52 +0200)] 
http: cleanup function fetch_and_setup_pack_index()

Cleanup the function `fetch_and_setup_pack_index()` by removing the
useless call to the function `unlink()`.

This is not necessary anymore since 63aca3f7f1 (dumb-http: store
downloaded pack idx as tempfile, 2024-10-25), when `fetch_pack_index()`
started registering its return value (in this case `tmp_idx`) as a
tempfile to be deleted at process exit.

Signed-off-by: LorenzoPegorari <lorenzo.pegorari2002@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: drop pointer to the "files" source
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:41 +0000 (10:20 +0200)] 
odb/source-loose: drop pointer to the "files" source

Now that all callbacks of the loose source operate on `struct
odb_source_loose` directly we no longer have to reach into the "files"
source at all.

Drop this field and update `odb_source_loose_new()` to instead accept
all parameters required to initialize itself. This ensures that the
"loose" backend is a fully standalone source.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: stub out remaining callbacks
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:40 +0000 (10:20 +0200)] 
odb/source-loose: stub out remaining callbacks

Stub out remaining callback functions for the "loose" backend.

Note that we also stub out transactions for loose objects. In fact, we
already have the infrastructure in place for those, and we could in
theory implement those, as well. But there are separate efforts ongoing
to polish up transactional interfaces, and doing so now would likely
result in some messiness. This omission will thus be worked on in a
subsequent patch series, once the dust has settled.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `write_object_stream()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:39 +0000 (10:20 +0200)] 
odb/source-loose: wire up `write_object_stream()` callback

Wire up the `write_object_stream()` callback.

Note that we don't move the implementation into "odb/source-loose.c".
This is because most of the logic to write loose objects is still
contained in "object-file.c", and detangling that requires us to do some
refactorings as explained in the preceding commit. So for now, the
implementation of writing an object stream is still located in
"object-file.c".

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoobject-file: refactor writing objects to use loose source
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:38 +0000 (10:20 +0200)] 
object-file: refactor writing objects to use loose source

The "object-file" subsystem still hosts the majority of logic used to
write loose objects. Eventually, we'll want to move this logic into
"odb/source-loose.c", but this isn't yet easily possible because a lot
of the writing logic is still being shared with `force_object_loose()`.

We will eventually detangle this logic so that we can indeed move all of
it into the "loose" source. Meanwhile though, refactor the code so that
it operates on a `struct odb_source_loose` directly to already make the
dependency explicit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `write_object()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:37 +0000 (10:20 +0200)] 
odb/source-loose: wire up `write_object()` callback

Move `odb_source_loose_write_object()` from "object-file.c" into
"odb/source-loose.c" and wire it up as the `write_object()` callback of
the loose source.

As in preceding commits, this requires us to expose a couple of generic
functions from "object-file.c" as they are used in both subsystems now.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoloose: refactor object map to operate on `struct odb_source_loose`
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:36 +0000 (10:20 +0200)] 
loose: refactor object map to operate on `struct odb_source_loose`

While the loose object map functions in "loose.c" accept a generic
`struct odb_source *`, they always expect this to be the "files"
backend. Furthermore, the subsystem doesn't even care about the "files"
backend, but only uses it as a stepping stone to get to the "loose"
backend.

This assumption is implicit and thus not immediately obvious. Refactor
the interfaces to instead operate on a `struct odb_source_loose`
instead, which eliminates the implicit dependency and unnecessary detour
via the "files" source.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `freshen_object()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:35 +0000 (10:20 +0200)] 
odb/source-loose: wire up `freshen_object()` callback

Move `odb_source_loose_freshen_object()` from "object-file.c" into
"odb/source-loose.c" and wire it up as the `freshen_object()` callback
of the loose source.

As part of the move, `check_and_freshen_source()` is inlined into the
callback function, as it has no other callers anymore.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: drop `odb_source_loose_has_object()`
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:34 +0000 (10:20 +0200)] 
odb/source-loose: drop `odb_source_loose_has_object()`

The function `odb_source_loose_has_object()` checks whether a specific
object exists as a loose object on disk by using lstat(3p). This
interface is somewhat redundant, as we typically check for object
existence in a generic way via `odb_source_read_object_info()`.

In fact, these two calls are redundant in case the latter is called in a
specific way: when called without an object info request and without the
`OBJECT_INFO_QUICK` flag, then we will end up doing the same call to
lstat(3p) in `read_object_info_from_path()`.

Drop the function and adapt callers to instead use the generic
interface so that its calling conventions align with that of other
sources.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `count_objects()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:33 +0000 (10:20 +0200)] 
odb/source-loose: wire up `count_objects()` callback

Move `odb_source_loose_count_objects()` and its associated helpers from
"object-file.c" into "odb/source-loose.c" and wire it up as the
`count_objects()` callback of the loose source.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `find_abbrev_len()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:32 +0000 (10:20 +0200)] 
odb/source-loose: wire up `find_abbrev_len()` callback

Move `odb_source_loose_find_abbrev_len()` and its associated helpers
from "object-file.c" into "odb/source-loose.c" and wire it up as the
`find_abbrev_len` callback of the loose source.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `for_each_object()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:31 +0000 (10:20 +0200)] 
odb/source-loose: wire up `for_each_object()` callback

Move `odb_source_loose_for_each_object()` and its associated helpers
from "object-file.c" into "odb/source-loose.c" and wire it up as the
`for_each_object()` callback of the loose source.

Again, as in the preceding commit, we are forced to expose a couple of
functions from "object-file.c" that are now used by both subsystems.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `read_object_stream()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:30 +0000 (10:20 +0200)] 
odb/source-loose: wire up `read_object_stream()` callback

Move `odb_source_loose_read_object_stream()` and its associated helpers
from "object-file.c" into "odb/source-loose.c" and wire it up as the
`read_object_stream()` callback of the loose source.

As part of the move we are also forced to expose a couple of functions
from "object-file.h" that parse object headers in a somewhat-generic
way, as those functions are now used by both subsystems.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `read_object_info()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:29 +0000 (10:20 +0200)] 
odb/source-loose: wire up `read_object_info()` callback

Move `odb_source_loose_read_object_info()` from "object-file.c" into
"odb/source-loose.c" and wire it up as the `read_object_info()` callback
of the loose source. Callers that previously invoked it directly now go
through the generic `odb_source_read_object_info()` interface instead.

The function `read_object_info_from_path()` cannot be moved along with
it because it is still called by `for_each_object_wrapper_cb()`. It is
therefore kept in place, but adjusted to take a loose source to clarify
that it's always operating on this structure.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `close()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:28 +0000 (10:20 +0200)] 
odb/source-loose: wire up `close()` callback

Wire up a new `close()` callback for the loose source and call it from
the "files" source via the generic `odb_source_close()` interface. The
callback itself is a no-op as the loose source has no resources that
need to be released on close.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: wire up `reprepare()` callback
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:27 +0000 (10:20 +0200)] 
odb/source-loose: wire up `reprepare()` callback

Move `odb_source_loose_reprepare()` from "object-file.c" into
"odb/source-loose.c" and wire it up as the `reprepare()` callback of the
loose source.

While at it, make `odb_source_loose_clear_cache()` static, as it is no
longer needed outside of its file.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: start converting to a proper `struct odb_source`
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:26 +0000 (10:20 +0200)] 
odb/source-loose: start converting to a proper `struct odb_source`

Start converting `struct odb_source_loose` into a proper pluggable
`struct odb_source` by embedding the base struct and assigning it the
new `ODB_SOURCE_LOOSE` type. Furthermore, wire up lifecycle management
of this source by implementing the `free` callback and taking ownership
of the chdir notifications.

Note that the loose source is not yet functional as a standalone `struct
odb_source`, as it's missing all of the callback implementations. These
will be wired up in subsequent commits.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: store pointer to "files" instead of generic source
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:25 +0000 (10:20 +0200)] 
odb/source-loose: store pointer to "files" instead of generic source

The `struct odb_source_loose` holds a pointer to its owning parent
source. The way that Git is currently structured, this parent is always
the "files" source. In subsequent commits we're going to detangle that
so that the "loose" source doesn't have any owning parent source at all
so that it can be used as a completely standalone source.

Detangling this mess is somewhat intricate though, and is made even more
intricate because it's not always clear which kind of source one is
holding at a specific point in time -- either the parent "files" source,
or the child "loose" source.

Make this relationship more explicit by storing a pointer to the "files"
source instead of storing a pointer to a generic `struct odb_source`.
This will help make subsequent steps a bit clearer.

Note that this is a temporary step, only. At the end of this series
we will have dropped the parent pointer completely.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agoodb/source-loose: move loose source into "odb/" subsystem
Patrick Steinhardt [Mon, 1 Jun 2026 08:20:24 +0000 (10:20 +0200)] 
odb/source-loose: move loose source into "odb/" subsystem

In subsequent patches we'll be turning `struct odb_source_loose` into a
proper `struct odb_source`. As a first step towards this goal, move its
struct out of "object-file.c" and into "odb/source-loose.c".

This detaches the implementation of the loose object source from the
generic object file code, following the same convention already used by
the "files" and "in-memory" sources.

No functional changes are intended.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
12 days agogit-gui: remove unnecessary 'cd $_gitworktree' from do_gitk
Johannes Sixt [Sun, 31 May 2026 23:02:15 +0000 (19:02 -0400)] 
git-gui: remove unnecessary 'cd $_gitworktree' from do_gitk

In the procedure that invokes Gitk, we have a 'cd $_gitworktree'. Such
a change of the current directory is not necessary, because

- if we have a working tree, then the startup routine has already
  changed the current directory to the root of the working tree, which
  *is* $_gitworktree; or

- if we are in a bare repository, then there is no point in changing
  the current directory anywhere. (And $_gitworktree is empty.)

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
12 days agogit-gui: use HEAD as current branch when detached
Mark Levedahl [Sun, 31 May 2026 23:02:14 +0000 (19:02 -0400)] 
git-gui: use HEAD as current branch when detached

commit f87a36b697 ("git-gui: use git-branch --show-current", 2024-02-12)
changed git-gui to use git-branch to access refs, rather than directly
reading files as doing the latter is not compatible with the reftable
backend. git branch --show-current reports an empty branch name when the
head is detached, and in this case load_current_branch needs to report
HEAD using special case logic as it did prior to the above commit. Make
it do so.

This addresses an issue with git-gui browser failing with a detached
head.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
13 days agoThe 10th batch
Junio C Hamano [Sun, 31 May 2026 01:00:11 +0000 (10:00 +0900)] 
The 10th batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 days agoMerge branch 'sp/doc-range-diff-takes-notes'
Junio C Hamano [Sun, 31 May 2026 01:00:39 +0000 (10:00 +0900)] 
Merge branch 'sp/doc-range-diff-takes-notes'

Docfix.

* sp/doc-range-diff-takes-notes:
  Documentation/git-range-diff: add missing notes options in synopsis

13 days agoMerge branch 'ps/gitlab-ci-macOS-improvements'
Junio C Hamano [Sun, 31 May 2026 01:00:38 +0000 (10:00 +0900)] 
Merge branch 'ps/gitlab-ci-macOS-improvements'

Update GitLab CI jobs that exercise macOS.

* ps/gitlab-ci-macOS-improvements:
  gitlab-ci: update macOS image
  gitlab-ci: upgrade macOS runners

13 days agoMerge branch 'sa/cat-file-batch-mailmap-switch'
Junio C Hamano [Sun, 31 May 2026 01:00:38 +0000 (10:00 +0900)] 
Merge branch 'sa/cat-file-batch-mailmap-switch'

"git cat-file --batch" learns an in-line command "mailmap"
that lets the user toggle use of mailmap.

* sa/cat-file-batch-mailmap-switch:
  cat-file: add mailmap subcommand to --batch-command

13 days agoMerge branch 'jk/commit-graph-lazy-load-fallback'
Junio C Hamano [Sun, 31 May 2026 01:00:38 +0000 (10:00 +0900)] 
Merge branch 'jk/commit-graph-lazy-load-fallback'

The logic to lazy-load trees from the commit-graph has been made
more robust by falling back to reading the commit object when
the commit-graph is no longer available.

* jk/commit-graph-lazy-load-fallback:
  commit: fall back to full read when maybe_tree is NULL

13 days agoMerge branch 'pt/fsmonitor-linux'
Junio C Hamano [Sun, 31 May 2026 01:00:38 +0000 (10:00 +0900)] 
Merge branch 'pt/fsmonitor-linux'

The fsmonitor daemon has been implemented for Linux.

* pt/fsmonitor-linux:
  fsmonitor: convert shown khash to strset in do_handle_client
  fsmonitor: add tests for Linux
  fsmonitor: add timeout to daemon stop command
  fsmonitor: close inherited file descriptors and detach in daemon
  run-command: add close_fd_above_stderr option
  fsmonitor: implement filesystem change listener for Linux
  fsmonitor: rename fsm-settings-darwin.c to fsm-settings-unix.c
  fsmonitor: rename fsm-ipc-darwin.c to fsm-ipc-unix.c
  fsmonitor: use pthread_cond_timedwait for cookie wait
  compat/win32: add pthread_cond_timedwait
  fsmonitor: fix hashmap memory leak in fsmonitor_run_daemon
  fsmonitor: fix khash memory leak in do_handle_client
  t9210, t9211: disable GIT_TEST_SPLIT_INDEX for scalar clone tests

13 days agoMerge branch 'ps/graph-lane-limit'
Junio C Hamano [Sun, 31 May 2026 01:00:37 +0000 (10:00 +0900)] 
Merge branch 'ps/graph-lane-limit'

The graph output from commands like "git log --graph" can now be
limited to a specified number of lanes, preventing overly wide output
in repositories with many branches.

* ps/graph-lane-limit:
  graph: add truncation mark to capped lanes
  graph: add --graph-lane-limit option
  graph: limit the graph width to a hard-coded max

13 days agoMerge branch 'jr/bisect-custom-terms-in-output'
Junio C Hamano [Sun, 31 May 2026 01:00:37 +0000 (10:00 +0900)] 
Merge branch 'jr/bisect-custom-terms-in-output'

"git bisect" now uses the selected terms (e.g., old/new) more
consistently in its output.

* jr/bisect-custom-terms-in-output:
  rev-parse: use selected alternate terms to look up refs
  bisect: print bisect terms in single quotes
  bisect: use selected alternate terms in status output

13 days agoMerge branch 'tc/generate-configlist-fix-for-older-ninja'
Junio C Hamano [Sun, 31 May 2026 01:00:37 +0000 (10:00 +0900)] 
Merge branch 'tc/generate-configlist-fix-for-older-ninja'

Build update.

* tc/generate-configlist-fix-for-older-ninja:
  generate-configlist: collapse depfile for older Ninja

13 days agoMerge branch 'kk/tips-reachable-from-bases-optim'
Junio C Hamano [Sun, 31 May 2026 01:00:37 +0000 (10:00 +0900)] 
Merge branch 'kk/tips-reachable-from-bases-optim'

Revision traversal optimization.

* kk/tips-reachable-from-bases-optim:
  t6600: add tests for duplicate tips in tips_reachable_from_bases()
  commit-reach: use object flags for tips_reachable_from_bases()

13 days agoMerge branch 'ed/check-connected-close-err-fd'
Junio C Hamano [Sun, 31 May 2026 01:00:36 +0000 (10:00 +0900)] 
Merge branch 'ed/check-connected-close-err-fd'

File descriptor leak fix.

* ed/check-connected-close-err-fd:

13 days agoMerge branch 'ed/check-connected-close-err-fd-2.53'
Junio C Hamano [Sun, 31 May 2026 01:00:36 +0000 (10:00 +0900)] 
Merge branch 'ed/check-connected-close-err-fd-2.53'

File descriptor leak fix (for 2.54 maintenance track).

* ed/check-connected-close-err-fd-2.53:
  connected: close err_fd in promisor fast-path

2 weeks agodaemon: guard NULL REMOTE_PORT in execute() logging
Sebastien Tardif [Thu, 28 May 2026 02:56:56 +0000 (02:56 +0000)] 
daemon: guard NULL REMOTE_PORT in execute() logging

REMOTE_ADDR and REMOTE_PORT are both set by the same code path in
handle(), so when the existing REMOTE_ADDR check passes, REMOTE_PORT
is guaranteed to be non-NULL.  Guard REMOTE_PORT as well so that a
future change that breaks this invariant does not pass NULL to
printf's %s, which is undefined behavior.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agodaemon: fix IPv6 address truncation in ip2str()
Sebastien Tardif [Thu, 28 May 2026 02:56:55 +0000 (02:56 +0000)] 
daemon: fix IPv6 address truncation in ip2str()

The sockaddr struct size (ai_addrlen) is passed as the output buffer
size to inet_ntop(). For IPv6, sizeof(sockaddr_in6) is 28 bytes but
INET6_ADDRSTRLEN is 46, so long IPv6 addresses are silently truncated.

Fix this by passing sizeof(ip) instead, which is the actual size of
the destination buffer. Drop the now-unused len parameter from
ip2str() and update all callers.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agodaemon: fix IPv6 address corruption in lookup_hostname()
Sebastien Tardif [Thu, 28 May 2026 02:56:54 +0000 (02:56 +0000)] 
daemon: fix IPv6 address corruption in lookup_hostname()

getaddrinfo() is called with AF_UNSPEC hints, so it may return IPv6
results. However, the code unconditionally casts ai_addr to
sockaddr_in and passes AF_INET to inet_ntop(). On IPv6-only hosts,
this reads from the wrong struct offset, producing garbage IP
addresses.

Fix this by checking ai_family and extracting the address pointer
into a local variable before calling inet_ntop() once with the
correct family. Die on unexpected address families.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agoline-log: allow non-patch diff formats with -L
Michael Montalbo [Thu, 28 May 2026 20:47:46 +0000 (20:47 +0000)] 
line-log: allow non-patch diff formats with -L

Now that -L flows through log_tree_diff_flush() and diff_flush(),
metadata-only diff formats work because they only read filepair
fields (status, mode, path, oid) already set on the pre-computed
pairs.

Expand the allowlist in setup_revisions() to also accept --raw,
--name-only, --name-status, and --summary.  Diff stat formats
(--stat, --numstat, --shortstat, --dirstat) remain blocked because
they call compute_diffstat() on full blob content and would show
whole-file statistics rather than range-scoped ones.

Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agoline-log: integrate -L output with the standard log-tree pipeline
Michael Montalbo [Thu, 28 May 2026 20:47:45 +0000 (20:47 +0000)] 
line-log: integrate -L output with the standard log-tree pipeline

`git log -L` has bypassed log_tree_diff() and log_tree_diff_flush()
since the feature was introduced, short-circuiting from
log_tree_commit() directly into line_log_print().  This skips the
no_free save/restore (noted in a NEEDSWORK comment added by
f8781bfda3), the always_show_header fallback, show_diff_of_diff(),
and diff_free() cleanup.

Restructure so that -L flows through log_tree_diff() ->
log_tree_diff_flush(), the same path used by the normal
single-parent and merge diff codepaths:

 - Rename line_log_print() to line_log_queue_pairs() and strip it
   down to just queuing pre-computed filepairs.  The show_log(),
   separator, diffcore_std(), and diff_flush() calls are removed
   since log_tree_diff_flush() handles all of those.

 - In log_tree_diff(), call line_log_queue_pairs() then
   log_tree_diff_flush(), mirroring the diff_tree_oid() + flush
   pattern used by the single-parent and merge codepaths.

 - Remove the early return in log_tree_commit() that is no longer
   needed now that -L output flows through log_tree_diff() and
   log_tree_diff_flush(); this restores no_free save/restore,
   always_show_header, and diff_free() cleanup.

Because show_log() is now deferred until after diffcore_std() inside
log_tree_diff_flush(), pickaxe (-S, -G, --find-object) and
--diff-filter now properly suppress commits when all pairs are
filtered out.

The blank-line separator between commit header and diff changes
slightly: the old code printed one unconditionally, while
log_tree_diff_flush() only emits one for verbose headers.  This
matches the rest of log output.

Also reject --full-diff, which is not yet supported with -L: the
filepairs are pre-computed during the history walk and scoped to
tracked line ranges, so there is currently no full-tree diff to
fall back to for display.

Update tests accordingly.

Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agorevision: move -L setup before output_format-to-diff derivation
Michael Montalbo [Thu, 28 May 2026 20:47:44 +0000 (20:47 +0000)] 
revision: move -L setup before output_format-to-diff derivation

The line_level_traverse block sets a default DIFF_FORMAT_PATCH when
no output format has been explicitly requested.  This default must
be visible to the "Did the user ask for any diff output?" check
that derives revs->diff from revs->diffopt.output_format.

Currently the -L block runs after that derivation, so revs->diff
stays 0 when no explicit format is given.  This does not matter yet
because log_tree_commit() short-circuits into line_log_print()
before consulting revs->diff, but the next commit will route -L
through the normal log_tree_diff() path, which checks revs->diff.

Move the block above the derivation so the default DIFF_FORMAT_PATCH
is in place when revs->diff is computed.  No behavior change on its
own.

Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agodoc: clarify that --word-diff operates on line-level hunks
Michael Montalbo [Thu, 28 May 2026 19:21:45 +0000 (19:21 +0000)] 
doc: clarify that --word-diff operates on line-level hunks

The --word-diff documentation describes the output modes and
word-regex mechanics but does not explain that word-diff operates
within the hunks produced by the line-level diff rather than
performing an independent word-stream comparison.  This can
surprise users when the line-level alignment causes word-level
changes to appear even though the words in both files are
identical.

Add an implementation note explaining the two-stage relationship
and that the output may change if Git acquires a different
implementation in the future.

Signed-off-by: Michael Montalbo <mmontalbo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agot3070: skip ls-files tests with backslash patterns on Windows
Kristofer Karlsson [Thu, 28 May 2026 09:00:48 +0000 (09:00 +0000)] 
t3070: skip ls-files tests with backslash patterns on Windows

On Windows (MINGW), backslashes in pathspecs are silently converted to
forward slashes (directory separators), which changes the glob semantics.
This causes 36 test failures in t3070-wildmatch when the "via ls-files"
variants test patterns containing backslash escapes (e.g. '\[ab]',
'[\-_]', '[A-\\]').

The wildmatch function itself handles these patterns correctly — only the
ls-files code path fails because pathspec parsing converts the
backslashes before they reach the glob matcher.

Skip these ls-files tests on platforms where BSLASHPSPEC is not set,
which is the existing prereq that captures exactly this semantic:
"backslashes in pathspec are not directory separators."

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agocommit: remove deprecated functions
Kristoffer Haugsbakk [Thu, 28 May 2026 07:00:11 +0000 (09:00 +0200)] 
commit: remove deprecated functions

These functions were deprecated in a series of commits merged in
52882024 (Merge branch 'ps/commit-list-functions-renamed', 2026-02-13).

The compatibility was for in-flight topics at the time.

Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks ago*: replace deprecated free_commit_list
Kristoffer Haugsbakk [Thu, 28 May 2026 07:00:10 +0000 (09:00 +0200)] 
*: replace deprecated free_commit_list

Replace `free_commit_list` with `commit_list_free`. The former was
deprecated in 9f18d089 (commit: rename `free_commit_list()` to conform
to coding guidelines, 2026-01-15).

This allows us to remove all the deprecated functions in the
next commit:

• `copy_commit_list`
• `reverse_commit_list`
• `free_commit_list`

Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: build pseudo-merge bitmaps after regular bitmaps
Taylor Blau [Wed, 27 May 2026 19:56:11 +0000 (15:56 -0400)] 
pack-bitmap: build pseudo-merge bitmaps after regular bitmaps

When generating bitmaps, `bitmap_builder_init()` starts with an initial
selection of commits to receive bitmap coverage, and then determines a
set of "maximal" commits based on its input.

Commit 089f751360f (pack-bitmap-write: build fewer intermediate bitmaps,
2020-12-08) has extensive details, but the gist is as follows:

Each selected commit starts with one commit_mask bit in its "commit
mask" bitmap. Then, we walk the first-parent history in topological
order and OR each commit's mask into its (first) parent. Whenever that
OR results in the parent having more bits set, the child is deemed to be
non-maximal, and the frontier is pushed further back along the first
parent history.

That approach works extremely well for ordinary selected commits, whose
first-parent histories often describe real sharing between the bitmaps
we are going to write.

It struggles, however, to efficiently generate pseudo-merge bitmaps.
Unlike ordinary commits for which the above algorithm is designed,
pseudo-merges don't represent any "real" commit in history, just a
grouping of non-bitmapped reference tips. In that sense, their first
parent is just a part of a larger set, and treating them like ordinary
selected commits imposes a significant slow-down when generating bitmaps
with pseudo-merges enabled.

Consider partitioning all non-bitmapped reference tips into eight
individual pseudo-merges via the following configuration:

    [bitmapPseudoMerge "all"]
        pattern=refs/
        threshold=now
        stableSize=10000000
        maxMerges=8

, the cost of generating a bitmap from scratch rises significantly:

    +------------------+-----------------+---------------+---------------------+
    |                  | no pseudo-merge | pseudo-merges | Delta               |
    |                  |                 | (HEAD^)       |                     |
    +------------------+-----------------+---------------+---------------------+
    | elapsed          |   294.1 s       |   575.0 s     |   +280.9 s (+95.5%) |
    | cycles           | 1,365.5 B       | 2,686.9 B     | +1,321.4 B (+96.8%) |
    | instructions     | 1,389.8 B       | 2,546.6 B     | +1,156.8 B (+83.2%) |
    | CPI              |     0.983       |     1.055     |   +0.073    (+7.4%) |
    +------------------+-----------------+---------------+---------------------+

This is a particularly poor trade-off, because the time saved by these
pseudo-merges during, e.g.,

    $ git rev-list --count --all --objects --use-bitmap-index

is only:

    $ hyperfine -L v true,false -n 'pseudo-merges: {v}' '
        GIT_TEST_USE_PSEUDO_MERGES={v} git.compile rev-list --count \
          --objects --all --use-bitmap-index
      '

    Benchmark 1: pseudo-merges: true
      Time (mean ± σ):      2.613 s ±  0.012 s    [User: 2.308 s, System: 0.305 s]
      Range (min … max):    2.594 s …  2.633 s    10 runs

    Benchmark 2: pseudo-merges: false
      Time (mean ± σ):     52.205 s ±  0.170 s    [User: 51.500 s, System: 0.697 s]
      Range (min … max):   51.956 s … 52.458 s    10 runs

    Summary
      pseudo-merges: true ran
       19.98 ± 0.11 times faster than pseudo-merges: false

In other words, we pay a nearly ~5 minute penalty to generate
pseudo-merge bitmaps, but only save ~50 seconds during traversal.

The problem stems from injecting pseudo-merges into the bitmap builder
as if they were normal commits. The maximal commit selection algorithm
was simply not designed for that case, and performs predictably poorly.

The only reason we reused the maximal commit selection routine for
pseudo-merges alongside regular non-pseudo-merge commits is because we
represent them both as commit objects (where the pseudo-merge commits
just represent a made-up commit as opposed to one that actually exists
in a repository's object store).

Instead, build the regular selected commit bitmaps first, considering
only non-pseudo-merge commits in `bitmap_builder_init()`. Once those
bitmaps have been stored, build each pseudo-merge bitmap separately and
attach its parent and object bitmaps to the corresponding pseudo-merge
entry before writing the extension.

This keeps the regular bitmap build shaped like the no-pseudo-merge
case. The later pseudo-merge fill can still stop at stored selected
ancestor bitmaps, so it does not have to rewalk each pseudo-merge
closure from scratch.

When an existing bitmap has the same pseudo-merge parent set, reuse and
remap that whole pseudo-merge bitmap before falling back to
fill_bitmap_commit(). This preserves the benefit of stable pseudo-merges
while keeping the on-disk format and reader behavior unchanged.

As a result, the overhead cost for generating pseudo-merges in the above
configuration is much smaller:

    +------------------+-----------------+---------------+-------------------+
    |                  | no pseudo-merge | pseudo-merges | Delta             |
    |                  |                 | (HEAD)        |                   |
    +------------------+-----------------+---------------+-------------------+
    | elapsed          |   294.1 s       |   328.4 s     |  +34.3 s (+11.7%) |
    | cycles           | 1,365.5 B       | 1,529.3 B     | +163.7 B (+12.0%) |
    | instructions     | 1,389.8 B       | 1,552.8 B     | +163.0 B (+11.7%) |
    | CPI              |     0.983       |     0.985     |  +0.002   (+0.2%) |
    +------------------+-----------------+---------------+-------------------+

Recall that at the start of this series, generating reachability bitmaps
took 612.5 seconds *without* pseudo-merges. With this commit, it is
still ~46.38% *faster* to generate reachability bitmaps *with*
pseudo-merges than it was to generate bitmaps wihtout them at the
beginning of this series.

The changes to implement this are mostly straightforward. We exclude
pseudo-merge commits from the existing bitmap generation, and walk over
them in a separate pass, by either reusing an existing on-disk
pseudo-merge, or passing the pseudo-merge commit itself back to the
existing routine in `fill_bitmap_commit()`.

(Note that the routine to build pseudo-merge bitmaps is the same both
before and after this change, the difference is only that we do not let
psuedo-merges participate in determining the set of maximal commits.)

The only wrinkle is that `fill_bitmap_commit()` must be taught to not
expect that all tree objects have been parsed, which is the case for any
portion of history reachable by one or more pseudo-merge(s), but not by
any non-pseudo-merge commit selected for bitmapping.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: remember pseudo-merge parents
Taylor Blau [Wed, 27 May 2026 19:56:08 +0000 (15:56 -0400)] 
pack-bitmap: remember pseudo-merge parents

write_pseudo_merges() currently builds an array of temporary bitmaps for
the parent set of each pseudo-merge, then serializes those bitmaps later
while writing the extension.

Move those parent bitmaps onto the corresponding bitmapped_commit
entries instead. This keeps the on-disk output unchanged, but gives the
parent bitmap the same lifetime and access pattern that later changes
will use when pseudo-merge object bitmaps are built before the write
step.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: sort bitmaps before XORing
Taylor Blau [Wed, 27 May 2026 19:56:05 +0000 (15:56 -0400)] 
pack-bitmap: sort bitmaps before XORing

Reachability bitmaps may be stored as XORs against nearby bitmaps, up to
10 away. However, when callers provide selected commits in an arbitrary
order, the writer may miss good ancestor/descendant pairs and produce
much larger bitmap files without changing query coverage.

Sort the selected bitmaps in date order (from oldest to newest) before
computing XOR offsets, leaving pseudo-merge bitmaps alone (which we will
deal with separately in following commits).

On our same testing repository from previous commits, this change shrunk
our selection of 1,261 bitmaps from ~635.46 MiB to 176.4 MiB for a
~72.24% reduction in the on-disk size of our *.bitmap file. The time to
generate the smaller bitmap file decreased by ~3.69 seconds, though this
is likely mostly noise.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: cache object positions during fill
Taylor Blau [Wed, 27 May 2026 19:56:02 +0000 (15:56 -0400)] 
pack-bitmap: cache object positions during fill

The previous commits removed some redundant work from bitmap generation
by avoiding unnecessary tree recursion and by reusing selected bitmaps
that have already been computed.

Even with those changes in place, there is still an extremely hot path
from `fill_bitmap_commit()` and `fill_bitmap_tree()` to translate object
IDs into their corresponding bit positions in order to generate their
bitmaps.

In a small repository, this overhead is not significant. However, in a
very large repository (e.g., the one that we have been using as a
benchmark over the past several commits with ~57M total objects), the
overhead of locating object bit positions (often repeatedly) adds up
significantly.

Combat this by adding a small, direct-mapped cache to the bitmap writer
which maps object IDs to their corresponding bit positions. Size the
cache according to the number of objects being written, with fixed lower
and upper bounds so small repositories do not pay for a large table and
large repositories can avoid most repeated packlist and MIDX lookups.

On my machine with (a somewhat outdated) GCC 15.2.0, each entry in the
cache is 40 bytes wide:

    $ pahole -C bitmap_pos_cache_entry pack-bitmap-write.o
    struct bitmap_pos_cache_entry {
            struct object_id           oid;                  /*     0    36 */
            uint32_t                   pos;                  /*    36     4 */

            /* size: 40, cachelines: 1, members: 2 */
            /* last cacheline: 40 bytes */
    };

, and we will allocate up to 2^21 entries for a maximum total of 80 MiB
of cache overhead.

In our example repository from above and in earlier commits, this
results in a ~9.4% reduction in runtime relative to the previous commit:

    +------------------+-------------+-------------+---------------------+
    |                  | HEAD^       | HEAD        | Delta               |
    +------------------+-------------+-------------+---------------------+
    | elapsed          |   324.8 s   |   294.1 s   |    -30.7 s  (-9.4%) |
    | cycles           | 1,508.6 B   | 1,365.5 B   |   -143.0 B  (-9.5%) |
    | instructions     | 1,436.6 B   | 1,389.8 B   |    -46.9 B  (-3.3%) |
    | CPI              |     1.050   |     0.983   |   -0.068    (-6.4%) |
    +------------------+-------------+-------------+---------------------+

When generating bitmaps on this repository (to produce the above
timings), the cache grew to its maximum size of 80 MiB, and resulted in
1.024B cache hits and 59.957M cache misses.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: consolidate `find_object_pos()` success path
Taylor Blau [Wed, 27 May 2026 19:55:59 +0000 (15:55 -0400)] 
pack-bitmap: consolidate `find_object_pos()` success path

Both sides of `find_object_pos()` report success in the same way by
setting the optional `found` out-parameter and return the resolved
bitmap position.

Prepare for adding more bookkeeping around object-position lookups by
storing the result in a local `pos` variable and sharing the success
return path between the packlist and MIDX cases.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: reuse stored selected bitmaps
Taylor Blau [Wed, 27 May 2026 19:55:56 +0000 (15:55 -0400)] 
pack-bitmap: reuse stored selected bitmaps

When `fill_bitmap_commit()` reaches an ancestor that was selected for
its own bitmap and processed earlier, its object closure is already
stored in `writer->bitmaps` as an EWAH bitmap. As a result, walking
through that commit's tree and parents again is redundant.

Teach `fill_bitmap_commit()` to notice that case. For non-root commits in
the walk, look for a stored selected bitmap and OR it into the bitmap
being built. If one exists, skip the commit, its tree, and its parents.

Building bitmaps from scratch on the same test repository from the
previous commits yields a significant speed-up:

    +------------------+-------------+-------------+---------------------+
    |                  | HEAD^       | HEAD        | Delta               |
    +------------------+-------------+-------------+---------------------+
    | elapsed          |   562.8 s   |   324.8 s   |   -237.9 s (-42.3%) |
    | cycles           | 2,621.3 B   | 1,508.6 B   | -1,112.7 B (-42.4%) |
    | instructions     | 2,348.9 B   | 1,436.6 B   |   -912.3 B (-38.8%) |
    | CPI              |     1.116   |     1.050   |   -0.066    (-5.9%) |
    +------------------+-------------+-------------+---------------------+

In our testing repository, there are 1,261 commits selected for bitmap
coverage, and 1,382 maximal commits induced as a result of that. Of the
1,382 calls made to `fill_bitmap_commit()` (one per maximal commit), 131
of them can be short-circuited at some point during their traversal as a
consequence of this change.

In large repositories where the cost of filling the bitmap for any
individual commit is large, being able to short-circuit even ~9.5% of
the calls to `fill_bitmap_commit()` results in a significant savings.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: check subtree bits before recursing
Taylor Blau [Wed, 27 May 2026 19:55:53 +0000 (15:55 -0400)] 
pack-bitmap: check subtree bits before recursing

In the previous commit, we adjusted the callers of `fill_bitmap_tree()`
to pass in the bit position of the tree they wish to fill.

This commit makes use of that information at the call site to avoid
setting up a stack frame for fill_bitmap_tree() entirely whenever a
tree's bit position is already set.

Since this is such a hot path, the avoided cost of setting up and
tearing down stack frames for each noop'd call to `fill_bitmap_tree()`
is significant:

    +--------------+-------------+-------------+-------------------+
    |              | HEAD^       | HEAD        | Delta             |
    +--------------+-------------+-------------+-------------------+
    | elapsed      |   582.4 s   |   562.8 s   |  -19.6 s  (-3.4%) |
    | cycles       | 2,713.3 B   | 2,621.3 B   |  -92.0 B  (-3.4%) |
    | instructions | 2,415.5 B   | 2,348.9 B   |  -66.6 B  (-2.8%) |
    | CPI          |     1.123   |     1.116   |  -0.007   (-0.7%) |
    +--------------+-------------+-------------+-------------------+

In the same repository as in the previous commit, our timings dropped
from ~582.4 seconds down to ~562.77 seconds.

While the cycles-per-instruction ratio is basically unchanged, we
execute significantly fewer instructions, and correspondingly fewer
cycles.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agopack-bitmap: pass object position to `fill_bitmap_tree()`
Taylor Blau [Wed, 27 May 2026 19:55:50 +0000 (15:55 -0400)] 
pack-bitmap: pass object position to `fill_bitmap_tree()`

In the following commit, callers of `fill_bitmap_tree()` will be
required to check the bit corresponding to their tree before calling
that function. That change will reduce the overhead of setting up and
tearing down stack frames for trees whose bits are already set.

To prepare for that change, have callers pass in the tree's bit position
in `fill_bitmap_tree()`, which will make the next commit easier to read.

In the meantime, this change has a surprising and measurable benefit
during bitmap generation, particularly on very large repositories.

When processing sub-trees within `fill_bitmap_tree()`, the preimage of
this patch did the following:

    while (tree_entry(&desc, entry)) {
        switch (object_type(entry.mode)) {
        case OBJ_TREE:
            if (fill_bitmap_tree(writer, bitmap,
                                 lookup_tree(writer->repo,
                                             &entry.oid)) < 0) {
                /* ... */
            }
            /* ... */
        }
    }

, first performing the object lookup via `lookup_tree()`, and then
locating its bit position within the recursive call. This patch
effectively reorders those two calls so that we first discover the
sub-tree's bit position, *then* load its tree.

By reordering these two operations, we spend fewer CPU cycles per
instruction, likely due to improved CPU dependency/cache/pipeline
behavior. Comparing the results of: running `perf stat` before and after
this commit, we have:

    +--------------+-------------+-------------+-------------------+
    |              | HEAD^       | HEAD        | Delta             |
    +--------------+-------------+-------------+-------------------+
    | elapsed      |   612.5 s   |   582.4 s   |  -30.1 s  (-4.9%) |
    | cycles       | 2,857.3 B   | 2,713.3 B   | -144.0 B  (-5.0%) |
    | instructions | 2,413.2 B   | 2,415.5 B   |   +2.3 B  (+0.1%) |
    | CPI          |     1.184   |     1.123   |  -0.061   (-5.1%) |
    +--------------+-------------+-------------+-------------------+

In a large repository with ~4.8M commit, and ~37.1M tree objects this
change improves timing from ~612.5 seconds down to ~582.4 seconds, or a
~4.9% improvement. More importantly, the number of CPU cycles spent
dropped off significantly as a result of this commit, lowering our
cycles-per-instruction ratio by about ~5.1%.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agoThe 9th batch
Junio C Hamano [Wed, 27 May 2026 05:15:25 +0000 (14:15 +0900)] 
The 9th batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agoMerge branch 'ps/setup-wo-the-repository'
Junio C Hamano [Wed, 27 May 2026 05:15:46 +0000 (14:15 +0900)] 
Merge branch 'ps/setup-wo-the-repository'

Many uses of the_repository has been updated to use a more
appropriate struct repository instance in setup.c codepath.

* ps/setup-wo-the-repository:
  setup: stop using `the_repository` in `init_db()`
  setup: stop using `the_repository` in `create_reference_database()`
  setup: stop using `the_repository` in `initialize_repository_version()`
  setup: stop using `the_repository` in `check_repository_format()`
  setup: stop using `the_repository` in `upgrade_repository_format()`
  setup: stop using `the_repository` in `setup_git_directory()`
  setup: stop using `the_repository` in `setup_git_directory_gently()`
  setup: stop using `the_repository` in `setup_git_env()`
  setup: stop using `the_repository` in `set_git_work_tree()`
  setup: stop using `the_repository` in `setup_work_tree()`
  setup: stop using `the_repository` in `enter_repo()`
  setup: stop using `the_repository` in `verify_non_filename()`
  setup: stop using `the_repository` in `verify_filename()`
  setup: stop using `the_repository` in `path_inside_repo()`
  setup: stop using `the_repository` in `prefix_path()`
  setup: stop using `the_repository` in `is_inside_work_tree()`
  setup: stop using `the_repository` in `is_inside_git_dir()`
  setup: replace use of `the_repository` in static functions

2 weeks agoMerge branch 'ps/odb-in-memory'
Junio C Hamano [Wed, 27 May 2026 05:15:46 +0000 (14:15 +0900)] 
Merge branch 'ps/odb-in-memory'

Add a new odb "in-memory" source that is meant to only hold
tentative objects (like the virtual blob object that represents the
working tree file used by "git blame").

* ps/odb-in-memory:
  t/unit-tests: add tests for the in-memory object source
  odb: generic in-memory source
  odb/source-inmemory: stub out remaining functions
  odb/source-inmemory: implement `freshen_object()` callback
  odb/source-inmemory: implement `count_objects()` callback
  odb/source-inmemory: implement `find_abbrev_len()` callback
  odb/source-inmemory: implement `for_each_object()` callback
  odb/source-inmemory: convert to use oidtree
  oidtree: add ability to store data
  cbtree: allow using arbitrary wrapper structures for nodes
  odb/source-inmemory: implement `write_object_stream()` callback
  odb/source-inmemory: implement `write_object()` callback
  odb/source-inmemory: implement `read_object_stream()` callback
  odb/source-inmemory: implement `read_object_info()` callback
  odb: fix unnecessary call to `find_cached_object()`
  odb/source-inmemory: implement `free()` callback
  odb: introduce "in-memory" source