]> git.ipfire.org Git - thirdparty/git.git/log
thirdparty/git.git
3 weeks agoMerge branch 'rs/diff-quiet-no-rename'
Junio C Hamano [Fri, 21 Nov 2025 17:14:15 +0000 (09:14 -0800)] 
Merge branch 'rs/diff-quiet-no-rename'

As "git diff --quiet" only cares about the existence of any
changes, disable rename/copy detection to skip more expensive
processing whose result will be discarded anyway.

* rs/diff-quiet-no-rename:
  diff: disable rename detection with --quiet

3 weeks agoStart 2.53 cycle
Junio C Hamano [Wed, 19 Nov 2025 18:55:15 +0000 (10:55 -0800)] 
Start 2.53 cycle

Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoMerge branch 'ps/ref-peeled-tags-fixes'
Junio C Hamano [Wed, 19 Nov 2025 18:55:40 +0000 (10:55 -0800)] 
Merge branch 'ps/ref-peeled-tags-fixes'

Another fix-up to "peeled-tags" topic.

* ps/ref-peeled-tags-fixes:
  object: fix performance regression when peeling tags

3 weeks agoMerge branch 'kn/refs-optim-cleanup'
Junio C Hamano [Wed, 19 Nov 2025 18:55:40 +0000 (10:55 -0800)] 
Merge branch 'kn/refs-optim-cleanup'

Code clean-up.

* kn/refs-optim-cleanup:
  t/pack-refs-tests: move the 'test_done' to callees
  refs: rename 'pack_refs_opts' to 'refs_optimize_opts'
  refs: move to using the '.optimize' functions

3 weeks agoMerge branch 'ps/ref-peeled-tags'
Junio C Hamano [Wed, 19 Nov 2025 18:55:39 +0000 (10:55 -0800)] 
Merge branch 'ps/ref-peeled-tags'

Some ref backend storage can hold not just the object name of an
annotated tag, but the object name of the object the tag points at.
The code to handle this information has been streamlined.

* ps/ref-peeled-tags:
  t7004: do not chdir around in the main process
  ref-filter: fix stale parsed objects
  ref-filter: parse objects on demand
  ref-filter: detect broken tags when dereferencing them
  refs: don't store peeled object IDs for invalid tags
  object: add flag to `peel_object()` to verify object type
  refs: drop infrastructure to peel via iterators
  refs: drop `current_ref_iter` hack
  builtin/show-ref: convert to use `reference_get_peeled_oid()`
  ref-filter: propagate peeled object ID
  upload-pack: convert to use `reference_get_peeled_oid()`
  refs: expose peeled object ID via the iterator
  refs: refactor reference status flags
  refs: fully reset `struct ref_iterator::ref` on iteration
  refs: introduce `.ref` field for the base iterator
  refs: introduce wrapper struct for `each_ref_fn`

3 weeks agoMerge branch 'ps/packed-git-in-object-store'
Junio C Hamano [Wed, 19 Nov 2025 18:55:37 +0000 (10:55 -0800)] 
Merge branch 'ps/packed-git-in-object-store'

The list of packfiles used in a running Git process is moved from
the packed_git structure into the packfile store.

* ps/packed-git-in-object-store:
  packfile: track packs via the MRU list exclusively
  packfile: always add packfiles to MRU when adding a pack
  packfile: move list of packs into the packfile store
  builtin/pack-objects: simplify logic to find kept or nonlocal objects
  packfile: fix approximation of object counts
  http: refactor subsystem to use `packfile_list`s
  packfile: move the MRU list into the packfile store
  packfile: use a `strmap` to store packs by name

4 weeks agoGit 2.52 maint v2.52.0
Junio C Hamano [Mon, 17 Nov 2025 15:35:33 +0000 (07:35 -0800)] 
Git 2.52

Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoMerge branch 'jc/ci-use-arm64-p4-on-macos'
Junio C Hamano [Mon, 17 Nov 2025 15:00:12 +0000 (07:00 -0800)] 
Merge branch 'jc/ci-use-arm64-p4-on-macos'

We replaced deprecated macos-13 with macos-14 image in GitHub
Actions CI, but we forgot that the image is for arm64.  We have
been seeing a lot of test failures ever since.  Switch to arm64
binary for Perforce tests.

* jc/ci-use-arm64-p4-on-macos:
  Use Perforce arm64 binary on macOS CI jobs

4 weeks agoUse Perforce arm64 binary on macOS CI jobs
Junio C Hamano [Sun, 16 Nov 2025 23:10:28 +0000 (15:10 -0800)] 
Use Perforce arm64 binary on macOS CI jobs

The previous step replaced deprecated macos-13 image with macos-14
image on GitHub Actions CI.  While x86-64 binaries can work there,
because macos-14 images are arm64 based (we could replace it with
macos-14-large that is x86-64), it makes more sense to use arm64
binary there.  Without this change, we have been getting unusually
higher rate of failures from random macOS CI jobs railing to run
t98xx series of tests.

Helped-by: Koji Nakamaru <koji.nakamaru@gree.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoMerge tag 'l10n-2.52.0-v1' of https://github.com/git-l10n/git-po
Junio C Hamano [Sun, 16 Nov 2025 18:36:50 +0000 (10:36 -0800)] 
Merge tag 'l10n-2.52.0-v1' of https://github.com/git-l10n/git-po

l10n-2.52.0-v1

* tag 'l10n-2.52.0-v1' of https://github.com/git-l10n/git-po:
  l10n: zh_CN: updated translation for 2.52
  l10n: uk: add 2.52 translation
  l10n: zh_TW.po: update Git 2.52 translation
  l10n: Updated translation for vi-2.52
  l10n: tr: Update Turkish translations
  l10n: po-id for 2.52
  l10n: ga.po: Update Irish translation for Git 2.52
  l10n: bg.po: Updated Bulgarian translation (6065t)
  l10n: fr: version 2.52
  l10n: sv.po: Update Swedish translation

4 weeks agol10n: zh_CN: updated translation for 2.52
Teng Long [Thu, 13 Nov 2025 11:53:51 +0000 (19:53 +0800)] 
l10n: zh_CN: updated translation for 2.52

Reviewed-by: 依云 <lilydjwg@gmail.com>
Signed-off-by: Teng Long <dyroneteng@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
4 weeks agoMerge branch '2.52-uk' of github.com:arkid15r/git-ukrainian-l10n
Jiang Xin [Sun, 16 Nov 2025 02:16:45 +0000 (10:16 +0800)] 
Merge branch '2.52-uk' of github.com:arkid15r/git-ukrainian-l10n

* '2.52-uk' of github.com:arkid15r/git-ukrainian-l10n:
  l10n: uk: add 2.52 translation

4 weeks agol10n: uk: add 2.52 translation
Arkadii Yakovets [Sat, 15 Nov 2025 18:02:21 +0000 (10:02 -0800)] 
l10n: uk: add 2.52 translation

Co-authored-by: Kate Golovanova <kate@kgthreads.com>
Signed-off-by: Arkadii Yakovets <ark@cho.red>
Signed-off-by: Kate Golovanova <kate@kgthreads.com>
4 weeks agoMerge branch 'vi-2.52' of github.com:Nekosha/git-po
Jiang Xin [Sat, 15 Nov 2025 14:16:10 +0000 (22:16 +0800)] 
Merge branch 'vi-2.52' of github.com:Nekosha/git-po

* 'vi-2.52' of github.com:Nekosha/git-po:
  l10n: Updated translation for vi-2.52

4 weeks agoMerge branch 'l10n/zh-TW/git-2-52' of github.com:l10n-tw/git-po
Jiang Xin [Sat, 15 Nov 2025 14:14:55 +0000 (22:14 +0800)] 
Merge branch 'l10n/zh-TW/git-2-52' of github.com:l10n-tw/git-po

* 'l10n/zh-TW/git-2-52' of github.com:l10n-tw/git-po:
  l10n: zh_TW.po: update Git 2.52 translation

4 weeks agoMerge branch 'po-id' of github.com:bagasme/git-po
Jiang Xin [Sat, 15 Nov 2025 14:10:16 +0000 (22:10 +0800)] 
Merge branch 'po-id' of github.com:bagasme/git-po

* 'po-id' of github.com:bagasme/git-po:
  l10n: po-id for 2.52

4 weeks agoMerge branch 'master' of github.com:alshopov/git-po
Jiang Xin [Sat, 15 Nov 2025 14:08:47 +0000 (22:08 +0800)] 
Merge branch 'master' of github.com:alshopov/git-po

* 'master' of github.com:alshopov/git-po:
  l10n: bg.po: Updated Bulgarian translation (6065t)

4 weeks agoMerge branch 'fr_v2.52' of github.com:jnavila/git
Jiang Xin [Sat, 15 Nov 2025 14:07:53 +0000 (22:07 +0800)] 
Merge branch 'fr_v2.52' of github.com:jnavila/git

* 'fr_v2.52' of github.com:jnavila/git:
  l10n: fr: version 2.52

4 weeks agoMerge branch 'l10n-ga-2.52' of github.com:aindriu80/git-po
Jiang Xin [Sat, 15 Nov 2025 14:06:01 +0000 (22:06 +0800)] 
Merge branch 'l10n-ga-2.52' of github.com:aindriu80/git-po

* 'l10n-ga-2.52' of github.com:aindriu80/git-po:
  l10n: ga.po: Update Irish translation for Git 2.52

4 weeks agoMerge branch 'master' of github.com:nafmo/git-l10n-sv
Jiang Xin [Sat, 15 Nov 2025 14:03:30 +0000 (22:03 +0800)] 
Merge branch 'master' of github.com:nafmo/git-l10n-sv

* 'master' of github.com:nafmo/git-l10n-sv:
  l10n: sv.po: Update Swedish translation

4 weeks agol10n: zh_TW.po: update Git 2.52 translation
Yi-Jyun Pan [Thu, 13 Nov 2025 14:47:40 +0000 (22:47 +0800)] 
l10n: zh_TW.po: update Git 2.52 translation

Reviewed-by: hms5232 <hms5232@hhming.moe>
Co-authored-by: Lumynous <lumynou5.tw@gmail.com>
Signed-off-by: Yi-Jyun Pan <pan93412@gmail.com>
4 weeks agol10n: Updated translation for vi-2.52
Vũ Tiến Hưng [Sat, 15 Nov 2025 05:48:03 +0000 (12:48 +0700)] 
l10n: Updated translation for vi-2.52

Signed-off-by: Vũ Tiến Hưng <newcomerminecraft@gmail.com>
4 weeks agol10n: tr: Update Turkish translations
Emir SARI [Tue, 4 Nov 2025 16:06:26 +0000 (19:06 +0300)] 
l10n: tr: Update Turkish translations

Signed-off-by: Emir SARI <emir_sari@icloud.com>
4 weeks agoRelNotes: fix typo in release notes for 2.52.0
Taylor Blau [Thu, 13 Nov 2025 17:02:26 +0000 (12:02 -0500)] 
RelNotes: fix typo in release notes for 2.52.0

Introduced via aea86cf00f (The nineteenth batch, 2025-10-14).

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agol10n: po-id for 2.52
Bagas Sanjaya [Wed, 12 Nov 2025 10:19:09 +0000 (17:19 +0700)] 
l10n: po-id for 2.52

Update following components:

  - add-patch.c
  - builtin/bisect.c
  - builtin/describe.c
  - builtin/fast-export.c
  - builtin/fast-import.c
  - builtin/fetch.c
  - builtin/for-each-ref.c
  - builtin/gc.c
  - builtin/log.c
  - builtin/pack-refs.c
  - builtin/range-diff.c
  - builtin/reflog.c
  - builtin/refs.c
  - builtin/remote.c
  - builtin/repo.c
  - builtin/sparse-checkout.c
  - command-list.h
  - config.c
  - diff-lib.c
  - diff.c
  - gpg-interface.c
  - midx-write.c
  - promisor-remote.c
  - range-diff.c
  - refs.c
  - refs/files-backend.c
  - refs/reftable-backend.c
  - remote.c
  - usage.c
  - git-send-email.perl

Translate following new components:

  - builtin/last-modified.c
  - http.h

Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com>
4 weeks agoMerge branch 'tc/last-modified-active-paths-optimization'
Junio C Hamano [Wed, 12 Nov 2025 19:45:24 +0000 (11:45 -0800)] 
Merge branch 'tc/last-modified-active-paths-optimization'

"git last-modified" was optimized by narrowing the set of paths to
follow as it dug deeper in the history.

* tc/last-modified-active-paths-optimization:
  last-modified: implement faster algorithm

4 weeks agoGit 2.52-rc2 v2.52.0-rc2
Junio C Hamano [Wed, 12 Nov 2025 16:17:06 +0000 (08:17 -0800)] 
Git 2.52-rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoMerge branch 'dk/make-git-contacts-executable'
Junio C Hamano [Wed, 12 Nov 2025 16:17:31 +0000 (08:17 -0800)] 
Merge branch 'dk/make-git-contacts-executable'

Building "git contacts" script (in contrib/) left the resulting
file unexecutable, which has been corrected.

* dk/make-git-contacts-executable:
  perl: also mark git-contacts executable

4 weeks agoMerge branch 'dk/meson-html-dir'
Junio C Hamano [Wed, 12 Nov 2025 16:17:31 +0000 (08:17 -0800)] 
Merge branch 'dk/meson-html-dir'

The build procedure based on meson learned to allow builders to
specify the directory to install HTML documents.

* dk/meson-html-dir:
  meson: make GIT_HTML_PATH configurable

4 weeks agoMerge branch 'tu/credential-wincred-makefile-update'
Junio C Hamano [Wed, 12 Nov 2025 16:17:30 +0000 (08:17 -0800)] 
Merge branch 'tu/credential-wincred-makefile-update'

Build procedure for Wincred credential helper has been updated.

* tu/credential-wincred-makefile-update:
  wincred: align Makefile with other Makefiles in contrib

5 weeks agodiff: disable rename detection with --quiet
René Scharfe [Sun, 9 Nov 2025 16:43:36 +0000 (17:43 +0100)] 
diff: disable rename detection with --quiet

Detecting renames and copies improves diff's output.  This effort is
wasted if we don't show any.  Disable detection in that case.

This actually fixes the error code when using the options --cached,
--find-copies-harder, --no-ext-diff and --quiet together:
run_diff_index() indirectly calls diff-lib.c::show_modified(), which
queues even non-modified entries using diff_change() because we need
them for copy detection.  diff_change() sets flags.has_changes, though,
which causes diff_can_quit_early() to declare we're done after seeing
only the very first entry -- way too soon.

Using --cached, --find-copies-harder and --quiet together without
--no-ext-diff was not affected even before, as it causes the flag
flags.diff_from_contents to be set, which disables the optimization
in a different way.

Reported-by: D. Ben Knoble <ben.knoble@gmail.com>
Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agol10n: ga.po: Update Irish translation for Git 2.52
Aindriú Mac Giolla Eoin [Fri, 7 Nov 2025 20:32:54 +0000 (20:32 +0000)] 
l10n: ga.po: Update Irish translation for Git 2.52

Refreshes the Irish translation for Git 2.52, including new strings and
consistency improvements. Verified with `git-po-helper check`.

Signed-off-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
5 weeks agol10n: bg.po: Updated Bulgarian translation (6065t)
Alexander Shopov [Fri, 7 Nov 2025 10:55:59 +0000 (11:55 +0100)] 
l10n: bg.po: Updated Bulgarian translation (6065t)

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
5 weeks agol10n: fr: version 2.52
Jean-Noël Avila [Sun, 9 Nov 2025 13:27:02 +0000 (14:27 +0100)] 
l10n: fr: version 2.52

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
5 weeks agol10n: sv.po: Update Swedish translation
Peter Krefting [Fri, 7 Nov 2025 14:54:20 +0000 (15:54 +0100)] 
l10n: sv.po: Update Swedish translation

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
5 weeks agoMerge branch 'dk/parseopt-optional-filename-fixes'
Junio C Hamano [Thu, 6 Nov 2025 23:17:01 +0000 (15:17 -0800)] 
Merge branch 'dk/parseopt-optional-filename-fixes'

A recently added configuration variable and command line option
syntax ":(optional)" for values that are of filename type
inconsistently behaved on an empty file (configuration took it
happily, while the command line option pretended as if it did not
exist), which has been corrected.

* dk/parseopt-optional-filename-fixes:
  parseopt: remove unreachable code
  parseopt: restore const qualifier to parsed filename
  config: use boolean type for a simple flag
  parseopt: use boolean type for a simple flag
  doc: clarify command equivalence comment
  parseopt: fix :(optional) at command line to only ignore missing files

5 weeks agoMerge branch 'cc/fast-import-export-i18n-cleanup'
Junio C Hamano [Thu, 6 Nov 2025 23:17:01 +0000 (15:17 -0800)] 
Merge branch 'cc/fast-import-export-i18n-cleanup'

Messages from fast-import/export are now marked for i18n.

* cc/fast-import-export-i18n-cleanup:
  gpg-interface: mark a string for translation
  fast-import: mark strings for translation
  fast-export: mark strings for translation
  gpg-interface: use left shift to define GPG_VERIFY_*
  gpg-interface: simplify ssh fingerprint parsing

5 weeks agoMerge branch 'js/ci-github-actions-update'
Junio C Hamano [Thu, 6 Nov 2025 22:52:57 +0000 (14:52 -0800)] 
Merge branch 'js/ci-github-actions-update'

CI updates.

* js/ci-github-actions-update:
  ci: update {download,upload}-artifact Action versions

5 weeks agoMerge branch 'pk/reflog-migrate-message-fix'
Junio C Hamano [Thu, 6 Nov 2025 22:52:56 +0000 (14:52 -0800)] 
Merge branch 'pk/reflog-migrate-message-fix'

Message fix.

* pk/reflog-migrate-message-fix:
  refs: add missing space in messages

5 weeks agoobject: fix performance regression when peeling tags
Patrick Steinhardt [Thu, 6 Nov 2025 08:52:54 +0000 (09:52 +0100)] 
object: fix performance regression when peeling tags

Our Bencher dashboards [1] have recently alerted us about a bunch of
performance regressions when writing references, specifically with the
reftable backend. There is a 3x regression when writing many refs with
preexisting refs in the reftable format, and a 10x regression when
migrating refs between backends in either of the formats.

Bisecting the issue lands us at 6ec4c0b45b (refs: don't store peeled
object IDs for invalid tags, 2025-10-23). The gist of the commit is that
we may end up storing peeled objects in both reftables and packed-refs
for corrupted tags, where the claimed tagged object type is different
than the actual tagged object type. This will then cause us to create
the `struct object *` with a wrong type, as well, and obviously nothing
good comes out of that.

The fix for this issue was to introduce a new flag to `peel_object()`
that causes us to verify the tagged object's type before writing it into
the refdb -- if the tag is corrupt, we skip writing the peeled value.
To verify whether the peeled value is correct we have to look up the
object type via the ODB and compare the actual type with the claimed
type, and that additional object lookup is costly.

This also explains why we see the regression only when writing refs with
the reftable backend, but we see the regression with both backends when
migrating refs:

  - The reftable backend knows to store peeled values in the new table
    immediately, so it has to try and peel each ref it's about to write
    to the transaction. So the performance regression is visible for all
    writes.

  - The files backend only stores peeled values when writing the
    packed-refs file, so it wouldn't hit the performance regression for
    normal writes. But on ref migrations we know to write all new values
    into the packed-refs file immediately, and that's why we see the
    regression for both backends there.

Taking a step back though reveals an oddity in the new verification
logic: we not only verify the _tagged_ object's type, but we also verify
the type of the tag itself. But this isn't really needed, as we wouldn't
hit the bug in such a case anyway, as we only hit the issue with corrupt
tags claiming an invalid type for the tagged object.

The consequence of this is that we now started to look up the target
object of every single reference we're about to write, regardless of
whether it even is a tag or not. And that is of course quite costly.

Fix the issue by only verifying the type of the tagged objects. This
means that we of course still have a performance hit for actual tags.
But this only happens for writes anyway, and I'd claim it's preferable
to not store corrupted data in the refdb than to be fast here. Rename
the flag accordingly to clarify that we only verify the tagged object's
type.

This fix brings performance back to previous levels:

    Benchmark 1: baseline
      Time (mean ± σ):      46.0 ms ±   0.4 ms    [User: 40.0 ms, System: 5.7 ms]
      Range (min … max):    45.0 ms …  47.1 ms    54 runs

    Benchmark 2: regression
      Time (mean ± σ):     140.2 ms ±   1.3 ms    [User: 77.5 ms, System: 60.5 ms]
      Range (min … max):   138.0 ms … 142.7 ms    20 runs

    Benchmark 3: fix
      Time (mean ± σ):      46.2 ms ±   0.4 ms    [User: 40.2 ms, System: 5.7 ms]
      Range (min … max):    45.0 ms …  47.3 ms    55 runs

    Summary
      update-ref: baseline
        1.00 ± 0.01 times faster than fix
        3.05 ± 0.04 times faster than regression

[1]: https://bencher.dev/perf/git/plots

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoMerge branch 'ps/ref-peeled-tags' into ps/ref-peeled-tags-fixes
Junio C Hamano [Thu, 6 Nov 2025 18:54:28 +0000 (10:54 -0800)] 
Merge branch 'ps/ref-peeled-tags' into ps/ref-peeled-tags-fixes

* ps/ref-peeled-tags:
  t7004: do not chdir around in the main process
  ref-filter: fix stale parsed objects
  ref-filter: parse objects on demand
  ref-filter: detect broken tags when dereferencing them
  refs: don't store peeled object IDs for invalid tags
  object: add flag to `peel_object()` to verify object type
  refs: drop infrastructure to peel via iterators
  refs: drop `current_ref_iter` hack
  builtin/show-ref: convert to use `reference_get_peeled_oid()`
  ref-filter: propagate peeled object ID
  upload-pack: convert to use `reference_get_peeled_oid()`
  refs: expose peeled object ID via the iterator
  refs: refactor reference status flags
  refs: fully reset `struct ref_iterator::ref` on iteration
  refs: introduce `.ref` field for the base iterator
  refs: introduce wrapper struct for `each_ref_fn`

5 weeks agoci: update {download,upload}-artifact Action versions
Johannes Schindelin [Thu, 6 Nov 2025 13:59:36 +0000 (13:59 +0000)] 
ci: update {download,upload}-artifact Action versions

Bumps `actions/upload-artifact` from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

Bumps `actions/download-artifact` from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

Originally-authored-by: dependabot[bot] <support@github.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agomeson: make GIT_HTML_PATH configurable
D. Ben Knoble [Tue, 4 Nov 2025 13:58:29 +0000 (08:58 -0500)] 
meson: make GIT_HTML_PATH configurable

Makefile-based builds can configure Git's internal HTML_PATH by defining
htmldir, which is useful for packagers that put documentation in
different locations. Gentoo, for example, uses version-suffixed
directories like ${prefix}/share/doc/git-2.51 and puts the HTML
documentation in an 'html' subdirectory of the same.

Propagate the same configuration knob to Meson-based builds so that
"git --html-path" on such systems can be configured to output the
correct directory.

Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoperl: also mark git-contacts executable
D. Ben Knoble [Tue, 4 Nov 2025 18:14:57 +0000 (13:14 -0500)] 
perl: also mark git-contacts executable

When installing git-contacts with Meson via -Dcontrib=contacts, the default
Perl generation fails to mark it executable. As a result, "git contacts"
reports "'contacts' is not a git command."

Unlike generate-script.sh, we aren't testing the basename here; so, glob
the script name in the case arm to match wherever the input comes from.

Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agowincred: align Makefile with other Makefiles in contrib
Thomas Uhle [Wed, 5 Nov 2025 19:55:19 +0000 (20:55 +0100)] 
wincred: align Makefile with other Makefiles in contrib

* Replace $(LOADLIBES) because it is deprecated since long and it is
  used nowhere else in the git project.
* Use $(gitexecdir) instead of $(libexecdir) because config.mak defines
  $(libexecdir) as $(prefix)/libexec, not as $(prefix)/libexec/git-core.
* Similar to other Makefiles, let install target rule create
  $(gitexecdir) to make sure the directory exists before copying the
  executable and also let it respect $(DESTDIR).
* Shuffle the lines for the default settings to align them with the
  other Makefiles in contrib/credential.
* Define .PHONY for all special targets (all, install, clean).

Signed-off-by: Thomas Uhle <thomas.uhle@mailbox.tu-dresden.de>
Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agorefs: add missing space in messages
Peter Krefting [Wed, 5 Nov 2025 21:47:17 +0000 (22:47 +0100)] 
refs: add missing space in messages

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoGit 2.52-rc1 v2.52.0-rc1
Junio C Hamano [Wed, 5 Nov 2025 21:41:41 +0000 (13:41 -0800)] 
Git 2.52-rc1

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoMerge branch 'jc/ci-use-macos-14'
Junio C Hamano [Wed, 5 Nov 2025 21:41:51 +0000 (13:41 -0800)] 
Merge branch 'jc/ci-use-macos-14'

The version of macos image used in GitHub CI has been updated to
macos-14, as the macos-13 that we have been using got deprecated.

* jc/ci-use-macos-14:
  GitHub CI: macos-13 images are no more

5 weeks agoMerge branch 'rz/t0450-bisect-doc-update'
Junio C Hamano [Wed, 5 Nov 2025 21:41:51 +0000 (13:41 -0800)] 
Merge branch 'rz/t0450-bisect-doc-update'

The help text and manual page of "git bisect" command have been
made consistent with each other.

* rz/t0450-bisect-doc-update:
  bisect: update usage and docs to match each other

5 weeks agoGitHub CI: macos-13 images are no more
Junio C Hamano [Tue, 4 Nov 2025 23:13:20 +0000 (15:13 -0800)] 
GitHub CI: macos-13 images are no more

As this image was deprecated on Sep 22nd, and will be dropped on Dec
4th, replace these jobs to use macos-14 images instead.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoparseopt: remove unreachable code
Junio C Hamano [Tue, 4 Nov 2025 17:34:20 +0000 (09:34 -0800)] 
parseopt: remove unreachable code

At this point in the code after running skip_prefix() on the
variable and receiving the result in the same variable, the contents
of the variable can never be NULL.  The function either (1) updates
the variable to point at a later part of the string it originally
pointed at, or (2) leaves it intact if the string does not have the
prefix.  (1) will never make the variable NULL, and (2) cannot be
the source of NULL, because the variable cannot be NULL before
calling skip_prefix(), which would die immediately by dereferencing
the NULL pointer in that case.

Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoparseopt: restore const qualifier to parsed filename
D. Ben Knoble [Sun, 2 Nov 2025 16:17:48 +0000 (11:17 -0500)] 
parseopt: restore const qualifier to parsed filename

This was unintentionally dropped in ccfcaf399f (parseopt: values of
pathname type can be prefixed with :(optional), 2025-09-28). Notably,
continue dropping the const qualifier when free'ing value; see
4049b9cfc0 (fix const issues with some functions, 2007-10-16) or
83838d5c1b (cast variable in call to free() in builtin/diff.c and
submodule.c, 2011-11-06) for more details on why.

Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoconfig: use boolean type for a simple flag
D. Ben Knoble [Sun, 2 Nov 2025 16:17:47 +0000 (11:17 -0500)] 
config: use boolean type for a simple flag

Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoparseopt: use boolean type for a simple flag
D. Ben Knoble [Sun, 2 Nov 2025 16:17:46 +0000 (11:17 -0500)] 
parseopt: use boolean type for a simple flag

Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodoc: clarify command equivalence comment
D. Ben Knoble [Sun, 2 Nov 2025 16:17:45 +0000 (11:17 -0500)] 
doc: clarify command equivalence comment

Documentation of command parsing for :(optional) includes a terse
comment; expand it to be clearer to readers.

Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoparseopt: fix :(optional) at command line to only ignore missing files
D. Ben Knoble [Sun, 2 Nov 2025 16:17:44 +0000 (11:17 -0500)] 
parseopt: fix :(optional) at command line to only ignore missing files

Unlike the configuration option magic, the parseopt code also ignores
empty files: compare implementations from ccfcaf399f (parseopt: values
of pathname type can be prefixed with :(optional), 2025-09-28) and
749d6d166d (config: values of pathname type can be prefixed with
:(optional), 2025-09-28).

Unify the 2 by not ignoring empty files, which is less surprising and
the intended semantics from the first patch for config.

Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoA bit more before rc1
Junio C Hamano [Tue, 4 Nov 2025 15:47:51 +0000 (07:47 -0800)] 
A bit more before rc1

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoMerge branch 'jk/doc-backslash-in-exclude'
Junio C Hamano [Tue, 4 Nov 2025 15:48:10 +0000 (07:48 -0800)] 
Merge branch 'jk/doc-backslash-in-exclude'

The patterns used in the .gitignore files use backslash in the way
documented for fnmatch(3); document as such to reduce confusion.

* jk/doc-backslash-in-exclude:
  doc: document backslash in gitignore patterns

6 weeks agoMerge branch 'jk/test-delete-gpgsig-leakfix'
Junio C Hamano [Tue, 4 Nov 2025 15:48:09 +0000 (07:48 -0800)] 
Merge branch 'jk/test-delete-gpgsig-leakfix'

Leakfix.

* jk/test-delete-gpgsig-leakfix:
  test-tool: fix leak in delete-gpgsig command

6 weeks agoMerge branch 'eb/t1016-hash-transition-fix'
Junio C Hamano [Tue, 4 Nov 2025 15:48:09 +0000 (07:48 -0800)] 
Merge branch 'eb/t1016-hash-transition-fix'

Test fix.

* eb/t1016-hash-transition-fix:
  t1016-compatObjectFormat: really freeze time for reproduciblity

6 weeks agoMerge branch 'kh/doc-checkout-markup-fix'
Junio C Hamano [Tue, 4 Nov 2025 15:48:08 +0000 (07:48 -0800)] 
Merge branch 'kh/doc-checkout-markup-fix'

Doc mark-up fix.

* kh/doc-checkout-markup-fix:
  doc: git-checkout: fix placeholder markup

6 weeks agoMerge branch 'xr/ref-debug-remove-on-disk'
Junio C Hamano [Tue, 4 Nov 2025 15:48:08 +0000 (07:48 -0800)] 
Merge branch 'xr/ref-debug-remove-on-disk'

The "debug" ref-backend was missing a method implementation, which
has been corrected.

* xr/ref-debug-remove-on-disk:
  refs: add missing remove_on_disk implementation for debug backend

6 weeks agoMerge branch 'qj/doc-my1stcontrib-email-verify'
Junio C Hamano [Tue, 4 Nov 2025 15:48:07 +0000 (07:48 -0800)] 
Merge branch 'qj/doc-my1stcontrib-email-verify'

The "MyFirstContribution" tutorial tells the reader how to send out
their patches; the section gained a hint to verify the message
reached the mailing list.

* qj/doc-my1stcontrib-email-verify:
  MyFirstContribution: add note on confirming patches

6 weeks agoMerge branch 'tz/test-prepare-gnupghome'
Junio C Hamano [Tue, 4 Nov 2025 15:48:07 +0000 (07:48 -0800)] 
Merge branch 'tz/test-prepare-gnupghome'

Tests did not set up GNUPGHOME correctly, which is fixed but some
flaky tests are exposed in t1016, which needs to be addressed
before this topic can move forward.

* tz/test-prepare-gnupghome:
  t/lib-gpg: call prepare_gnupghome() in GPG2 prereq
  t/lib-gpg: add prepare_gnupghome() to create GNUPGHOME dir

6 weeks agoMerge branch 'jt/repo-structure'
Junio C Hamano [Tue, 4 Nov 2025 15:48:06 +0000 (07:48 -0800)] 
Merge branch 'jt/repo-structure'

"git repo structure", a new command.

* jt/repo-structure:
  builtin/repo: add progress meter for structure stats
  builtin/repo: add keyvalue and nul format for structure stats
  builtin/repo: add object counts in structure output
  builtin/repo: introduce structure subcommand
  ref-filter: export ref_kind_from_refname()
  ref-filter: allow NULL filter pattern
  builtin/repo: rename repo_info() to cmd_repo_info()

6 weeks agoMerge branch 'tu/credential-install'
Junio C Hamano [Tue, 4 Nov 2025 15:48:06 +0000 (07:48 -0800)] 
Merge branch 'tu/credential-install'

Contributed credential helpers (obviously in contrib/) now have "cd
$there && make install" target.

* tu/credential-install:
  contrib/credential: add install target

6 weeks agoMerge branch 'cc/doc-submitting-patches-with-ai'
Junio C Hamano [Tue, 4 Nov 2025 15:48:06 +0000 (07:48 -0800)] 
Merge branch 'cc/doc-submitting-patches-with-ai'

AI guidelines.

* cc/doc-submitting-patches-with-ai:
  SubmittingPatches: add section about AI

6 weeks agot/pack-refs-tests: move the 'test_done' to callees
Karthik Nayak [Mon, 20 Oct 2025 08:18:31 +0000 (10:18 +0200)] 
t/pack-refs-tests: move the 'test_done' to callees

In ac0bad0af4 (t0601: refactor tests to be shareable, 2025-09-19), we
refactored 't/t0601-reffiles-pack-refs.sh' to move all of the tests to
't/pack-refs-tests.sh', which became a common test suite which was also
used by 't/t1463-refs-optimize.sh'.

This also moved the 'test_done' directive to 't/pack-refs-tests.sh'.
Which inhibits additional tests from being added to either of the tests.
Let's move the directive out to both the tests, so that we can add
additional specific tests to them. Also the test flow logic shouldn't be
part of tests which can be embedded in other test scripts.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: rename 'pack_refs_opts' to 'refs_optimize_opts'
Karthik Nayak [Mon, 20 Oct 2025 08:18:30 +0000 (10:18 +0200)] 
refs: rename 'pack_refs_opts' to 'refs_optimize_opts'

The previous commit removed all references to 'pack_refs()' within
the refs subsystem. Continue this cleanup by also renaming
'pack_refs_opts' to 'refs_optimize_opts' and the respective flags
accordingly. Keeping the naming consistent will make the code easier to
maintain.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: move to using the '.optimize' functions
Karthik Nayak [Mon, 20 Oct 2025 08:18:29 +0000 (10:18 +0200)] 
refs: move to using the '.optimize' functions

The `struct ref_store` variable exposes two ways to optimize a reftable
backend:

  1. pack_refs
  2. optimize

The former was specific to the 'files' + 'packed' refs backend. The
latter is more generic and covers all backends. While the naming is
different, both of these functions perform the same functionality.

Consolidate this code to only maintain the 'optimize' functions. Do this
by modifying the backends so that they exclusively implement the
`optimize` callback, only. All users of the refs subsystem already use
the 'optimize' function so there is no changes needed on the callee
side. Finally, cleanup all references to the 'pack_refs' field of the
structure and code around it.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoMerge branch 'ps/ref-peeled-tags' into kn/refs-optim-cleanup
Junio C Hamano [Tue, 4 Nov 2025 15:33:41 +0000 (07:33 -0800)] 
Merge branch 'ps/ref-peeled-tags' into kn/refs-optim-cleanup

* ps/ref-peeled-tags: (92 commits)
  t7004: do not chdir around in the main process
  ref-filter: fix stale parsed objects
  ref-filter: parse objects on demand
  ref-filter: detect broken tags when dereferencing them
  refs: don't store peeled object IDs for invalid tags
  object: add flag to `peel_object()` to verify object type
  refs: drop infrastructure to peel via iterators
  refs: drop `current_ref_iter` hack
  builtin/show-ref: convert to use `reference_get_peeled_oid()`
  ref-filter: propagate peeled object ID
  upload-pack: convert to use `reference_get_peeled_oid()`
  refs: expose peeled object ID via the iterator
  refs: refactor reference status flags
  refs: fully reset `struct ref_iterator::ref` on iteration
  refs: introduce `.ref` field for the base iterator
  refs: introduce wrapper struct for `each_ref_fn`
  builtin/repo: add progress meter for structure stats
  builtin/repo: add keyvalue and nul format for structure stats
  builtin/repo: add object counts in structure output
  builtin/repo: introduce structure subcommand
  ...

6 weeks agot7004: do not chdir around in the main process
Junio C Hamano [Tue, 4 Nov 2025 15:28:59 +0000 (07:28 -0800)] 
t7004: do not chdir around in the main process

Move down to no-contains subdirectory inside a subshell, just like
the previous step that created and used it does.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoref-filter: fix stale parsed objects
Patrick Steinhardt [Tue, 4 Nov 2025 14:36:13 +0000 (15:36 +0100)] 
ref-filter: fix stale parsed objects

In 054f5f457e (ref-filter: parse objects on demand, 2025-10-23) we have
started to skip parsing some objects in case we don't need to access
their values in the first place. This was done by introducing a new
member `struct expand_data::maybe_object` that gets populated on demand
via `get_or_parse_object()`.

This has led to a regression though where the object now gets reused
because we don't reset it properly. The `oi` structure is declared in
global scope, and there is no single place where we reset it before
invoking `get_object()`. The consequence is that the `maybe_object`
member doesn't get reset across calls, so subsequent calls will end up
reusing the same object.

This is only an issue for a subset of retrieved values, as not all of
the infrastructure ends up calling `get_or_parse_object()`. So the
effect is limited, which is probably why the issue wasn't detected
earlier.

Fix the issue by resetting `maybe_object` in `get_object()`.

Reported-by: Junio C Hamano <gitster@pobox.com>
Based-on-patch-by: Jeff King <peff@peff.net>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoref-filter: parse objects on demand
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:23 +0000 (09:16 +0200)] 
ref-filter: parse objects on demand

When formatting an arbitrary object we parse that object regardless of
whether or not we actually need any parsed data. In fact, many of the
atoms we have don't require any.

Refactor the code so that we parse the data on demand when we see an
atom that wants to access the objects. This leads to a small speedup,
for example in the Chromium repository with around 40000 refs:

    Benchmark 1: for-each-ref --format='%(raw)' (HEAD~)
      Time (mean ± σ):     388.7 ms ±   1.1 ms    [User: 322.2 ms, System: 65.0 ms]
      Range (min … max):   387.3 ms … 390.8 ms    10 runs

    Benchmark 2: for-each-ref --format='%(raw)' (HEAD)
      Time (mean ± σ):     344.7 ms ±   0.7 ms    [User: 287.8 ms, System: 55.1 ms]
      Range (min … max):   343.9 ms … 345.7 ms    10 runs

    Summary
      for-each-ref --format='%(raw)' (HEAD) ran
        1.13 ± 0.00 times faster than for-each-ref --format='%(raw)' (HEAD~)

With this change, we now spend ~90% of the time decompressing objects,
which is almost as good as it gets regarding git-for-each-ref(1)'s own
infrastructure.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoref-filter: detect broken tags when dereferencing them
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:22 +0000 (09:16 +0200)] 
ref-filter: detect broken tags when dereferencing them

Users can ask git-for-each-ref(1) to peel tags and return information of
the tagged object by adding an asterisk to the format, like for example
"%(*$objectname)". If so, git-for-each-ref(1) peels that object to the
first non-tag object and then returns its values.

As mentioned in preceding commits, it can happen that the tagged object
type and the claimed object type differ, effectively resulting in a
corrupt tag. git-for-each-ref(1) would notice this mismatch, print an
error and then bail out when trying to peel the tag.

But we only notice this corruption in some very specific edge cases!
While we have a test in "t/for-each-ref-tests.sh" that verifies the
above scenario, this test is specifically crafted to detect the issue at
hand. Namely, we create two tags:

  - One tag points to a specific object with the correct type.

  - The other tag points to the *same* object with a different type.

The fact that both tags point to the same object is important here:
`peel_object()` wouldn't notice the corruption if the tagged objects
were different.

The root cause is that `peel_object()` calls `lookup_${type}()`
eventually, where the type is the same type declared in the tag object.
Consequently, when we have two tags pointing to the same object but with
different declared types we'll call two different lookup functions. The
first lookup will store the object with an unverified type A, whereas
the second lookup will try to look up the object with a different
unverified type B. And it is only now that we notice the discrepancy in
object types, even though type A could've already been the wrong type.

Fix the issue by verifying the object type in `populate_value()`. With
this change we'll also notice type mismatches when only dereferencing a
tag once.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: don't store peeled object IDs for invalid tags
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:21 +0000 (09:16 +0200)] 
refs: don't store peeled object IDs for invalid tags

Both the "files" and "reftable" backend store peeled object IDs for
references that point to tags:

  - The "files" backend stores the value when packing refs, where each
    peeled object ID is prefixed with "^".

  - The "reftable" backend stores the value whenever writing a new
    reference that points to a tag via a special ref record type.

Both of these backends use `peel_object()` to find the peeled object ID.
But as explained in the preceding commit, that function does not detect
the case where the tag's tagged object and its claimed type mismatch.

The consequence of storing these bogus peeled object IDs is that we're
less likely to detect such corruption in other parts of Git.
git-for-each-ref(1) for example does not notice anymore that the tag is
broken when using "--format=%(*objectname)" to dereference tags.

One could claim that this is good, because it still allows us to mostly
use the tag as intended. But the biggest problem here is that we now
have different behaviour for such a broken tag depending on whether or
not we have its peeled value in the refdb.

Fix the issue by verifying the object type when peeling the object. If
that verification fails we simply skip storing the peeled value in
either of the reference formats.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoobject: add flag to `peel_object()` to verify object type
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:20 +0000 (09:16 +0200)] 
object: add flag to `peel_object()` to verify object type

When peeling a tag to a non-tag object we repeatedly call
`parse_object()` on the tagged object until we find the first object
that isn't a tag. While this feels sensible at first, there is a big
catch here: `parse_object()` doesn't actually verify the type of the
tagged object.

The relevant code path here eventually ends up in `parse_tag_buffer()`.
Here, we parse the various fields of the tag, including the "type". Once
we've figured out the type and the tagged object ID, we call one of the
`lookup_${type}()` functions for whatever type we have found. There is
two possible outcomes in the successful case:

  1. The object is already part of our cached objects. In that case we
     double-check whether the type we're trying to look up matches the
     type that was cached.

  2. The object is _not_ part of our cached objects. In that case, we
     simply create a new object with the expected type, but we don't
     parse that object.

In the first case we might notice type mismatches, but only in the case
where our cache has the object with the correct type. In the second
case, we'll blindly assume that the type is correct and then go with it.
We'll only notice that the type might be wrong when we try to parse the
object at a later point.

Now arguably, we could change `parse_tag_buffer()` to verify the tagged
object's type for us. But that would have the effect that such a tag
cannot be parsed at all anymore, and we have a small bunch of tests for
exactly this case that assert we still can open such tags. So this
change does not feel like something we can retroactively tighten, even
though one shouldn't ever hit such corrupted tags.

Instead, add a new `flags` field to `peel_object()` that allows the
caller to opt in to strict object verification. This will be wired up at
a subset of callsites over the next few commits.

Note that this change also inlines `deref_tag_noverify()`. There's only
been two callsites of that function, the one we're changing and one in
our test helpers. The latter callsite can trivially use `deref_tag()`
instead, so by inlining the function we avoid having to pass down the
flag.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: drop infrastructure to peel via iterators
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:19 +0000 (09:16 +0200)] 
refs: drop infrastructure to peel via iterators

Now that the peeled object ID gets propagated via the `struct reference`
there is no need anymore to call into the reference iterator itself to
dereference an object. Remove this infrastructure.

Most of the changes are straight-forward deletions of code. There is one
exception though in `refs/packed-backend.c::write_with_updates()`. Here
we stop peeling the iterator and instead just pass the peeled object ID
of that iterator directly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: drop `current_ref_iter` hack
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:18 +0000 (09:16 +0200)] 
refs: drop `current_ref_iter` hack

In preceding commits we have refactored all callers of
`peel_iterated_oid()` to instead use `reference_get_peeled_oid()`. This
allows us to thus get rid of the former function.

Getting rid of that function is nice, but even nicer is that this also
allows us to get rid of the `current_ref_iter` hack. This global
variable tracked the currently-active ref iterator so that we can use it
to peel an object ID. Now that the peeled object ID is propagated via
`struct reference` though we don't have to depend on this hack anymore,
which makes for a more robust and easier-to-understand infrastructure.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agobuiltin/show-ref: convert to use `reference_get_peeled_oid()`
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:17 +0000 (09:16 +0200)] 
builtin/show-ref: convert to use `reference_get_peeled_oid()`

The git-show-ref(1) command has multiple different modes:

  - It knows to show all references matching a pattern.

  - It knows to list all references that are an exact match to whatever
    the user has provided.

  - It knows to check for reference existence.

The first two commands use mostly the same infrastructure to print the
references via `show_one()`. But while the former mode uses a proper
iterator and thus has a `struct reference` available in its context, the
latter calls `refs_read_ref()` and thus doesn't. Consequently, we cannot
easily use `reference_get_peeled_oid()` to print the peeled value.

Adapt the code so that we manually construct a `struct reference` when
verifying refs. We wouldn't ever have the peeled value available anyway
as we're not using an iterator here, so we can simply plug in the values
we _do_ have.

With this change we now have a `struct reference` available at both
callsites of `show_one()` and can thus pass it, which allows us to use
`reference_get_peeled_oid()` instead of `peel_iterated_oid()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoref-filter: propagate peeled object ID
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:16 +0000 (09:16 +0200)] 
ref-filter: propagate peeled object ID

When queueing a reference in the "ref-filter" subsystem we end up
creating a new ref array item that contains the reference's info. One
bit of info that we always discard though is the peeled object ID, and
because of that we are forced to use `peel_iterated_oid()`.

Refactor the code to propagate the peeled object ID via the ref array,
if available. This allows us to manually peel tags without having to go
through the object database.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoupload-pack: convert to use `reference_get_peeled_oid()`
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:15 +0000 (09:16 +0200)] 
upload-pack: convert to use `reference_get_peeled_oid()`

The `write_v0_ref()` callback is invoked from two callsites:

  - Once via `send_ref()` which is a callback passed to
    `for_each_namespaced_ref_1()` and `refs_head_ref_namespaced()`.

  - Once manually to announce capabilities.

When sending references to the client we also send the peeled value of
tags. As we don't have a `struct reference` available in the second
case, we cannot easily peel by calling `reference_get_peeled_oid()`, but
we instead have to depend on on global state via `peel_iterated_oid()`.

We do have a reference available though in the first case, it's only the
second case that keeps us from using `reference_get_peeled_oid()`. But
that second case only announces capabilities anyway, so we're not really
handling a reference at all here.

Adapt that case to construct a reference manually and pass that to
`write_v0_ref()`. Start to use `reference_get_peeled_oid()` now that we
always have a `struct reference` available.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: expose peeled object ID via the iterator
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:14 +0000 (09:16 +0200)] 
refs: expose peeled object ID via the iterator

Both the "files" and "reftable" backend are able to store peeled values
for tags in the respective formats. This allows for a more efficient
lookup of the target object of such a tag without having to manually
peel via the object database.

The infrastructure to access these peeled object IDs is somewhat funky
though. When iterating through objects, we store a pointer reference to
the current iterator in a global variable. The callbacks invoked by that
iterator are then expected to call `peel_iterated_oid()`, which checks
whether the globally-stored iterator's current reference refers to the
one handed into that function. If so, we ask the iterator to peel the
object, otherwise we manually peel the object via the object database.
Depending on global state like this is somewhat weird and also quite
fragile.

Introduce a new `struct reference::peeled_oid` field that can be
populated by the reference backends. This field can be accessed via a
new function `reference_get_peeled_oid()` that either uses that value,
if set, or alternatively peels via the ODB. With this change we don't
have to rely on global state anymore, but make the peeled object ID
available to the callback functions directly.

Adjust trivial callers that already have a `struct reference` available.
Remaining callers will be adjusted in subsequent commits.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: refactor reference status flags
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:13 +0000 (09:16 +0200)] 
refs: refactor reference status flags

The reference flags encode information like whether or not a reference
is a symbolic reference or whether it may be broken. This information is
stored in a `int flags` bitfield, which is in conflict with our modern
best practices; we tend to use an unsigned integer to store flags.

Change the type of the field to be `unsigned`. While at it, refactor the
individual flags to be part of an `enum` instead of using preprocessor
defines.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: fully reset `struct ref_iterator::ref` on iteration
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:12 +0000 (09:16 +0200)] 
refs: fully reset `struct ref_iterator::ref` on iteration

With the introduction of the `struct ref_iterator::ref` field it now is
a whole lot easier to introduce new fields that become accessible to the
caller without having to adapt every single callsite. But there's a
downside: when a new field is introduced we always have to adapt all
backends to set that field.

This isn't something we can avoid in the general case: when the new
field is expected to be populated by all backends we of course cannot
avoid doing so. But new fields may be entirely optional, in which case
we'd still have such churn. And furthermore, it is very easy right now
to leak state from a previous iteration into the next iteration.

Address this issue by ensuring that the reference backends all fully
reset the field on every single iteration. This ensures that no state
from previous iterations can leak into the next one. And it ensures that
any newly introduced fields will be zeroed out by default.

Note that we don't have to explicitly adapt the "files" backend, as it
uses the `cache_ref_iterator` internally. Furthermore, other "wrapping"
iterators like for example the `prefix_ref_iterator` copy around the
whole reference, so these don't need to be adapted either.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: introduce `.ref` field for the base iterator
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:11 +0000 (09:16 +0200)] 
refs: introduce `.ref` field for the base iterator

The base iterator has a couple of fields that tracks the name, target,
object ID and flags for the current reference. Due to this design we
have to create a new `struct reference` whenever we want to hand over
that reference to the callback function, which is tedious and not very
efficient.

Convert the structure to instead contain a `struct reference` as member.
This member is expected to be populated by the implementations of the
iterator and is handed over to the callback directly.

While at it, simplify `should_pack_ref()` to take a `struct reference`
directly instead of passing its respective fields.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: introduce wrapper struct for `each_ref_fn`
Patrick Steinhardt [Thu, 23 Oct 2025 07:16:10 +0000 (09:16 +0200)] 
refs: introduce wrapper struct for `each_ref_fn`

The `each_ref_fn` callback function type is used across our code base
for several different functions that iterate through reference. There's
a bunch of callbacks implementing this type, which makes any changes to
the callback signature extremely noisy. An example of the required churn
is e8207717f1 (refs: add referent to each_ref_fn, 2024-08-09): adding a
single argument required us to change 48 files.

It was already proposed back then [1] that we might want to introduce a
wrapper structure to alleviate the pain going forward. While this of
course requires the same kind of global refactoring as just introducing
a new parameter, it at least allows us to more change the callback type
afterwards by just extending the wrapper structure.

One counterargument to this refactoring is that it makes the structure
more opaque. While it is obvious which callsites need to be fixed up
when we change the function type, it's not obvious anymore once we use
a structure. That being said, we only have a handful of sites that
actually need to populate this wrapper structure: our ref backends,
"refs/iterator.c" as well as very few sites that invoke the iterator
callback functions directly.

Introduce this wrapper structure so that we can adapt the iterator
interfaces more readily.

[1]: <ZmarVcF5JjsZx0dl@tanuki>

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agolast-modified: implement faster algorithm
Toon Claes [Thu, 23 Oct 2025 07:50:14 +0000 (09:50 +0200)] 
last-modified: implement faster algorithm

The current implementation of git-last-modified(1) works by doing a
revision walk, and inspecting the diff at each level of that walk to
annotate entries remaining in the hashmap of paths. In other words, if
the diff at some level touches a path which has not yet been associated
with a commit, then that commit becomes associated with the path.

While a perfectly reasonable implementation, it can perform poorly in
either one of two scenarios:

  1. There are many entries of interest, in which case there is simply
     a lot of work to do.

  2. Or, there are (even a few) entries which have not been updated in a
     long time, and so we must walk through a lot of history in order to
     find a commit that touches that path.

This patch rewrites the last-modified implementation that addresses the
second point. The idea behind the algorithm is to propagate a set of
'active' paths (a path is 'active' if it does not yet belong to a
commit) up to parents and do a truncated revision walk.

The walk is truncated because it does not produce a revision for every
change in the original pathspec, but rather only for active paths.

More specifically, consider a priority queue of commits sorted by
generation number. First, enqueue the set of boundary commits with all
paths in the original spec marked as interesting.

Then, while the queue is not empty, do the following:

  1. Pop an element, say, 'c', off of the queue, making sure that 'c'
     isn't reachable by anything in the '--not' set.

  2. For each parent 'p' (with index 'parent_i') of 'c', do the
     following:

     a. Compute the diff between 'c' and 'p'.
     b. Pass any active paths that are TREESAME from 'c' to 'p'.
     c. If 'p' has any active paths, push it onto the queue.

  3. Any path that remains active on 'c' is associated to that commit.

This ends up being equivalent to doing something like 'git log -1 --
$path' for each path simultaneously. But, it allows us to go much faster
than the original implementation by limiting the number of diffs we
compute, since we can avoid parts of history that would have been
considered by the revision walk in the original implementation, but are
known to be uninteresting to us because we have already marked all paths
in that area to be inactive.

To avoid computing many first-parent diffs, add another trick on top of
this and check if all paths active in 'c' are DEFINITELY NOT in c's
Bloom filter. Since the commit-graph only stores first-parent diffs in
the Bloom filters, we can only apply this trick to first-parent diffs.

Comparing the performance of this new algorithm shows about a 2.5x
improvement on git.git:

    Benchmark 1: master   no bloom
      Time (mean ± σ):      2.868 s ±  0.023 s    [User: 2.811 s, System: 0.051 s]
      Range (min … max):    2.847 s …  2.926 s    10 runs

    Benchmark 2: master with bloom
      Time (mean ± σ):     949.9 ms ±  15.2 ms    [User: 907.6 ms, System: 39.5 ms]
      Range (min … max):   933.3 ms … 971.2 ms    10 runs

    Benchmark 3: HEAD     no bloom
      Time (mean ± σ):     782.0 ms ±   6.3 ms    [User: 740.7 ms, System: 39.2 ms]
      Range (min … max):   776.4 ms … 798.2 ms    10 runs

    Benchmark 4: HEAD   with bloom
      Time (mean ± σ):     307.1 ms ±   1.7 ms    [User: 276.4 ms, System: 29.9 ms]
      Range (min … max):   303.7 ms … 309.5 ms    10 runs

    Summary
      HEAD   with bloom ran
        2.55 ± 0.02 times faster than HEAD     no bloom
        3.09 ± 0.05 times faster than master with bloom
        9.34 ± 0.09 times faster than master   no bloom

In short, the existing implementation is comparably fast *with* Bloom
filters as the new implementation is *without* Bloom filters. So, most
repositories should get a dramatic speed-up by just deploying this (even
without computing Bloom filters), and all repositories should get faster
still when computing Bloom filters.

When comparing a more extreme example of
`git last-modified -- COPYING t`, the difference is even 5 times better:

    Benchmark 1: master
      Time (mean ± σ):      4.372 s ±  0.057 s    [User: 4.286 s, System: 0.062 s]
      Range (min … max):    4.308 s …  4.509 s    10 runs

    Benchmark 2: HEAD
      Time (mean ± σ):     826.3 ms ±  22.3 ms    [User: 784.1 ms, System: 39.2 ms]
      Range (min … max):   810.6 ms … 881.2 ms    10 runs

    Summary
      HEAD ran
        5.29 ± 0.16 times faster than master

As an added benefit, results are more consistent now. For example
implementation in 'master' gives:

    $ git log --max-count=1 --format=%H -- pkt-line.h
    15df15fe07ef66b51302bb77e393f3c5502629de

    $ git last-modified -- pkt-line.h
    15df15fe07ef66b51302bb77e393f3c5502629de pkt-line.h

    $ git last-modified | grep pkt-line.h
    5b49c1af03e600c286f63d9d9c9fb01403230b9f pkt-line.h

With the changes in this patch the results of git-last-modified(1)
always match those of `git log --max-count=1`.

One thing to note though, the results might be outputted in a different
order than before. This is not considerd to be an issue because nowhere
is documented the order is guaranteed.

Based-on-patches-by: Derrick Stolee <stolee@gmail.com>
Based-on-patches-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Toon Claes <toon@iotcl.com>
Acked-by: Taylor Blau <me@ttaylorr.com>
[jc: tweaked use of xcalloc() to unbreak coccicheck]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoGit 2.52-rc0 v2.52.0-rc0
Junio C Hamano [Mon, 3 Nov 2025 05:40:21 +0000 (21:40 -0800)] 
Git 2.52-rc0

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoMerge branch 'rs/merge-base-optim'
Junio C Hamano [Mon, 3 Nov 2025 14:49:55 +0000 (06:49 -0800)] 
Merge branch 'rs/merge-base-optim'

The code to walk revision graph to compute merge base has been
optimized.

* rs/merge-base-optim:
  commit-reach: avoid commit_list_insert_by_date()

6 weeks agoMerge branch 'jk/diff-patch-dry-run-cleanup'
Junio C Hamano [Mon, 3 Nov 2025 14:49:55 +0000 (06:49 -0800)] 
Merge branch 'jk/diff-patch-dry-run-cleanup'

Finishing touches to fixes to the recent regression in "git diff -w
--quiet" and anything that needs to internally generate patch to
see if it turns empty.

* jk/diff-patch-dry-run-cleanup:
  diff: simplify run_external_diff() quiet logic
  diff: drop dry-run redirection to /dev/null
  diff: replace diff_options.dry_run flag with NULL file
  diff: drop save/restore of color_moved in dry-run mode
  diff: send external diff output to diff_options.file

6 weeks agoMerge branch 'ps/maintenance-geometric'
Junio C Hamano [Mon, 3 Nov 2025 14:49:55 +0000 (06:49 -0800)] 
Merge branch 'ps/maintenance-geometric'

"git maintenance" command learns the "geometric" strategy where it
avoids doing maintenance tasks that rebuilds everything from
scratch.

* ps/maintenance-geometric:
  t7900: fix a flaky test due to git-repack always regenerating MIDX
  builtin/maintenance: introduce "geometric" strategy
  builtin/maintenance: make "gc" strategy accessible
  builtin/maintenance: extend "maintenance.strategy" to manual maintenance
  builtin/maintenance: run maintenance tasks depending on type
  builtin/maintenance: improve readability of strategies
  builtin/maintenance: don't silently ignore invalid strategy
  builtin/maintenance: make the geometric factor configurable
  builtin/maintenance: introduce "geometric-repack" task
  builtin/gc: make `too_many_loose_objects()` reusable without GC config
  builtin/gc: remove global `repack` variable

6 weeks agoMerge branch 'jk/match-pathname-fix'
Junio C Hamano [Mon, 3 Nov 2025 14:49:54 +0000 (06:49 -0800)] 
Merge branch 'jk/match-pathname-fix'

The wildmatch code had a corner case bug that mistakenly makes
"foo**/bar" match with "foobar", which has been corrected.

* jk/match-pathname-fix:
  match_pathname(): give fnmatch one char of prefix context
  match_pathname(): reorder prefix-match check

6 weeks agoMerge branch 'kh/doc-patch-id-1'
Junio C Hamano [Mon, 3 Nov 2025 14:49:54 +0000 (06:49 -0800)] 
Merge branch 'kh/doc-patch-id-1'

* kh/doc-patch-id-1:
  doc: patch-id: convert to the modern synopsis style

6 weeks agoMerge branch 'rs/add-patch-quit'
Junio C Hamano [Mon, 3 Nov 2025 14:49:54 +0000 (06:49 -0800)] 
Merge branch 'rs/add-patch-quit'

The 'q'(uit) command in "git add -p" has been improved to quit
without doing any meaningless work before leaving, and giving EOF
(typically control-D) to the prompt is made to behave the same way.

* rs/add-patch-quit:
  add-patch: quit on EOF
  add-patch: quit without skipping undecided hunks

6 weeks agoThe 27th batch
Junio C Hamano [Thu, 30 Oct 2025 14:34:16 +0000 (07:34 -0700)] 
The 27th batch

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoMerge branch 'rz/bisect-help-unknown'
Junio C Hamano [Thu, 30 Oct 2025 15:00:20 +0000 (08:00 -0700)] 
Merge branch 'rz/bisect-help-unknown'

"git bisect" command did not react correctly to "git bisect help"
and "git bisect unknown", which has been corrected.

* rz/bisect-help-unknown:
  bisect: fix handling of `help` and invalid subcommands

6 weeks agoMerge branch 'kf/log-shortlog-completion-fix'
Junio C Hamano [Thu, 30 Oct 2025 15:00:20 +0000 (08:00 -0700)] 
Merge branch 'kf/log-shortlog-completion-fix'

"git shortlog" knows "--committer" and "--author" options, which
the command line completion (in contrib/) did not handle well,
which has been corrected.

* kf/log-shortlog-completion-fix:
  completion: complete some 'git log' options

6 weeks agoMerge branch 'ly/diff-name-only-with-diff-from-content'
Junio C Hamano [Thu, 30 Oct 2025 15:00:19 +0000 (08:00 -0700)] 
Merge branch 'ly/diff-name-only-with-diff-from-content'

Regression fixes for a topic that has already been merged.

* ly/diff-name-only-with-diff-from-content:
  diff: stop output garbled message in dry run mode

6 weeks agoMerge branch 'ps/remove-packfile-store-get-packs'
Junio C Hamano [Thu, 30 Oct 2025 15:00:19 +0000 (08:00 -0700)] 
Merge branch 'ps/remove-packfile-store-get-packs'

Two slightly different ways to get at "all the packfiles" in API
has been cleaned up.

* ps/remove-packfile-store-get-packs:
  packfile: rename `packfile_store_get_all_packs()`
  packfile: introduce macro to iterate through packs
  packfile: drop `packfile_store_get_packs()`
  builtin/grep: simplify how we preload packs
  builtin/gc: convert to use `packfile_store_get_all_packs()`
  object-name: convert to use `packfile_store_get_all_packs()`