]> git.ipfire.org Git - thirdparty/git.git/log
thirdparty/git.git
2 weeks agoreset: drop `USE_THE_REPOSITORY_VARIABLE`
Patrick Steinhardt [Wed, 1 Jul 2026 11:35:29 +0000 (13:35 +0200)] 
reset: drop `USE_THE_REPOSITORY_VARIABLE`

In "reset.c" we still have references to `the_repository`, even though
the only entry point into the file already receives a repository as
parameter.

Update all uses of `the_repository` to instead use the passed-in repo
and drop `USE_THE_REPOSITORY_VARIABLE`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agoread-cache: split out function to drop unmerged entries to stage 0
Patrick Steinhardt [Wed, 1 Jul 2026 11:35:28 +0000 (13:35 +0200)] 
read-cache: split out function to drop unmerged entries to stage 0

In `repo_read_index_unmerged()` we read the index and then drop any
unmerged entries to stage 0. In a subsequent commit we'll want to
perform this operation on arbitrary indexes, not only the one of the
given repository.

Prepare for this by splitting out the functionality into a new function
that can act on an arbitrary index.

While at it, fix a signedness mismatch when iterating through the index
cache entries.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agoline-log: drop extra copy of range with bloom filters
Jeff King [Wed, 1 Jul 2026 06:42:03 +0000 (02:42 -0400)] 
line-log: drop extra copy of range with bloom filters

When line_log_process_ranges_arbitrary_commit() finds out from a Bloom
filter that a commit didn't touch the path in question, it can quickly
pass its range on to the parent commit.

It does so by making a copy of the range, and passing that copy to
add_line_range(). But add_line_range() already makes its own copy
(either directly, or by merging with an existing range for that parent).
So the copy we make is leaked.

We can plug the leak by just passing our range directly, without the
extra copy.

The bug goes back to f32dde8c12 (line-log: integrate with changed-path
Bloom filters, 2020-05-11). We didn't notice because the test suite
never explicitly combines these features! You can observe it by building
with SANITIZE=leak and running t4211 with some extra flags:

  GIT_TEST_COMMIT_GRAPH=1 \
  GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=1 \
  ./t4211-line-log.sh

It would probably be useful to have some more targeted test coverage of
these features together. But I don't think there's much point in just
blindly copying the existing tests and adding bloom-filter support. We
already do that via the linux-TEST-vars CI job. We just don't run the
leak-checking build with those flags (so if there were a correctness
problem, we'd have noticed, just not a leak).

So I think we'd benefit from somebody clueful thinking about the
interaction of these features and testing the corner cases. But for the
purposes of this leak fix, I think we can just rely on the recipe above
(and consider running an extra leak-test job with more TEST-vars set).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agorevision: avoid leaking bloom keyvecs with multiple traversals
Jeff King [Wed, 1 Jul 2026 06:40:52 +0000 (02:40 -0400)] 
revision: avoid leaking bloom keyvecs with multiple traversals

In prepare_revision_walk(), we convert the pruning pathspecs into
bloom-filter "keyvecs" via prepare_to_use_bloom_filter(). This allocates
memory which is then freed eventually by release_revisions(), via
release_revisions_bloom_keyvecs().

But there's one case where we leak. If a caller uses the same rev_info
for multiple walks, calling prepare_revision_walk() multiple times, then
subsequent calls will overwrite the earlier keyvecs, leaking them. This
can happen with "git show foo bar", which does a separate no-walk
traversal for "foo" and "bar". Building with SANITIZE=leak and running
the test suite like:

  GIT_TEST_COMMIT_GRAPH=1 \
  GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=1 \
  ./t4013-diff-various.sh

will trigger a complaint from LSan. It does not happen without those
extra flags because we don't store on-disk bloom filters by default, and
thus we optimize out the keyvec computation.

We can fix the leak by discarding the old entries before generating new
ones.

There's an alternative fix, which is that prepare_to_use_bloom_filter()
could notice that we already have keyvec entries and just reuse them.
But this is less safe; the keyvec depends on the pruning pathspec, and
we don't know if that has changed.

I think it would _probably_ work in practice, since any caller using a
rev_info for multiple traversals is probably doing so with the same
pathspec. But it would also create a very subtle bug if that assumption
is violated. So we'll do the safer thing here, and generate fresh keyvec
entries for each traversal. The efficiency difference is probably not
noticeable, and this is what was happening already (we just weren't
bothering to free the old ones!).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 weeks agobloom: make bloom-filter slab initialization idempotent
Jeff King [Wed, 1 Jul 2026 06:39:42 +0000 (02:39 -0400)] 
bloom: make bloom-filter slab initialization idempotent

Before using any of the commit-graph bloom-filter code, somebody needs
to call init_bloom_filters(). This initializes the commit-slab we use
for storing filter information. But we don't want to call it twice
(without a matching deinit call in the middle), since it overwrites the
existing slab pointers, leaking the old values.

Usually this init call is done lazily by parse_commit_graph() when we
read a graph file that contains bloom data. But this can lead to some
oddities:

  1. We may call parse_commit_graph() multiple times when we have a
     split commit graph. I think this doesn't produce any user-visible
     bug, because we parse all of the files back-to-back. So even though
     we call init_bloom_filters() multiple times, we never look up any
     commits in between, so the slab is always empty and initializing it
     again happens to do nothing. This is a little sketchy to rely on,
     though.

  2. We call init_bloom_filters() directly in the "test-tool bloom"
     helper so we can call get_or_compute_bloom_filter(). Normally this
     is OK, as there is no bloom data in the on-disk graph file. But if
     you build with SANITIZE=leak and run:

       GIT_TEST_COMMIT_GRAPH=1 \
       GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=1 \
       ./t0095-bloom.sh

     there's a leak that happens like this:

       a. Our direct init_bloom_filters() sets up the slab.

       b. In get_or_compute_bloom_filter() we look in the slab for a
  cached entry. We won't find anything yet, but since we don't
  use the read-only "peek" accessor (since we'll fill in the
  entry if not present), this actually populates the slab with
  an allocated chunk.

       c. Now we look for an entry in the graph files. So we have to
  load them and end up in parse_commit_graph(), which calls
  init_bloom_filters() again. That trashes our existing slab
  allocation, which is now leaked.

  3. There's a similar case in write_commit_graph(), which calls
     init_bloom_filters() before get_or_compute_bloom_filter(). I think
     this code path is lucky to avoid the leak because it reads the
     graph files first, then calls its init_bloom_filters(), and then
     starts filling in entries. So even though it has the same overwrite
     problem, we'd never actually allocate any slab entries between
     overwrites.

The easiest solution here is just to make initialization of the slab
idempotent using an extra flag.

We could actually get away without using the extra flag, for example by
checking whether bloom_filters.stride has been set. But it's probably
better to avoid being too intimate with the commit-slab details.
Likewise we don't actually need to re-initialize after a deinit call;
the slab-clearing function leaves things in a usable state. But it
seemed less surprising to pair the init/deinit calls explicitly.

I suspect this could all be cleaned up a bit more, but it's tricky. The
only function which uses the slab is get_or_compute_bloom_filter(), so
it would be much simpler if it just lazy-initialized the slab itself.
But I think there is a subtle dependency here: we usually only
initialize the slab when we find a graph file that has bloom entries. So
if we were to lose that signal, then even repos without on-disk bloom
data would start trying to populate the slab, wasting memory that will
never get entries filled in from the disk. So we'd need some other way
of signaling "it is worth considering bloom entries at all".

This patch takes a smaller and more direct route to just dealing with
the potential leak issue.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoMerge branch 'jk/repo-info-path-keys' into ps/setup-split-discovery-and-setup
Junio C Hamano [Tue, 30 Jun 2026 18:28:14 +0000 (11:28 -0700)] 
Merge branch 'jk/repo-info-path-keys' into ps/setup-split-discovery-and-setup

* jk/repo-info-path-keys:
  repo: add path.gitdir with absolute and relative suffix formatting
  repo: add path.commondir with absolute and relative suffix formatting
  path: extract format_path() and use in rev-parse

3 weeks agoMerge branch 'ps/setup-drop-global-state' into ps/setup-split-discovery-and-setup
Junio C Hamano [Tue, 30 Jun 2026 18:28:10 +0000 (11:28 -0700)] 
Merge branch 'ps/setup-drop-global-state' into ps/setup-split-discovery-and-setup

* ps/setup-drop-global-state:
  treewide: drop USE_THE_REPOSITORY_VARIABLE
  environment: stop using `the_repository` in `is_bare_repository()`
  environment: split up concerns of `is_bare_repository_cfg`
  builtin/init: stop modifying `is_bare_repository_cfg`
  setup: remove global `git_work_tree_cfg` variable
  builtin/init: simplify logic to configure worktree
  builtin/init: stop modifying global `git_work_tree_cfg` variable

3 weeks agoMerge branch 'ps/refs-onbranch-fixes' into ps/setup-split-discovery-and-setup
Junio C Hamano [Tue, 30 Jun 2026 18:27:30 +0000 (11:27 -0700)] 
Merge branch 'ps/refs-onbranch-fixes' into ps/setup-split-discovery-and-setup

* ps/refs-onbranch-fixes:
  refs: protect against chicken-and-egg recursion
  refs/reftable: lazy-load configuration to fix chicken-and-egg
  reftable: split up write options
  refs/files: lazy-load configuration to fix chicken-and-egg
  refs: move parsing of "core.logAllRefUpdates" back into ref stores
  repository: free main reference database
  chdir-notify: drop unused `chdir_notify_reparent()`
  refs: unregister reference stores from "chdir_notify"
  setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
  setup: stop applying repository format twice
  setup: inline `check_and_apply_repository_format()`

3 weeks agoformat-patch: fix leak of rev_info in prepare_bases()
Jeff King [Tue, 30 Jun 2026 06:43:01 +0000 (02:43 -0400)] 
format-patch: fix leak of rev_info in prepare_bases()

In prepare_bases() we do a custom revision walk, separate from the main
format-patch walk. After we finish, we fail to call release_revisions(),
possibly leaking its contents.

We failed to notice it so far because the revision machinery doesn't
always allocate. But at least one case can trigger the leak: if a commit
graph is present, then the topo-walk allocates revs.topo_walk_info and
some associated data structures. You can see it in the test suite by
running:

  make SANITIZE=leak
  cd t
  GIT_TEST_COMMIT_GRAPH=1 ./t4014-format-patch.sh

which yields many entries like:

  ==git==3687620==ERROR: LeakSanitizer: detected memory leaks
  Direct leak of 200 byte(s) in 1 object(s) allocated from:
      #0 0x7f4ccba185cb in malloc ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:74
      #1 0x55cd452cdd0b in do_xmalloc wrapper.c:55
      #2 0x55cd452cdd9d in xmalloc wrapper.c:76
      #3 0x55cd45255473 in init_topo_walk revision.c:3845
      #4 0x55cd45255bef in prepare_revision_walk revision.c:4017
      #5 0x55cd44ffec40 in prepare_bases builtin/log.c:1872
      #6 0x55cd450010ec in cmd_format_patch builtin/log.c:2439

The un-released rev_info has been there since the code was added in
fa2ab86d18 (format-patch: add '--base' option to record base tree info,
2016-04-26), but back then we didn't even have a way to release rev_info
resources! The actual leak probably started around f0d9cc4196
(revision.c: begin refactoring --topo-order logic, 2018-11-01), but it's
hard to bisect because there were so many other unrelated leaks back
then.

So I'm not sure exactly when the leak started beyond "long ago", but it
is easy-ish to find now (since we've plugged all those other leaks) and
the solution is clear.

I didn't add a new test since we can demonstrate it with the existing
ones, but it does require tweaking a test variable. We might consider
ways to get more automatic leak-checking coverage there, but I think it
should be done outside of this fix.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agot: move LSan errors from stdout to stderr
Jeff King [Tue, 30 Jun 2026 06:41:59 +0000 (02:41 -0400)] 
t: move LSan errors from stdout to stderr

When we find LSan errors, we dump them via "say_color", which goes to
stdout. This is mostly harmless, since stdout and stderr tend to go to
the same place (either the user's terminal, or to the ".out" file with
--verbose-log).

But when running under a TAP harness like prove, they are split and
stdout is interpreted as TAP output. Historically even this was fine, as
the extra lines on stdout would be ignored. But since 389c83025d (t: let
prove fail when parsing invalid TAP output, 2026-06-04) we instruct the
TAP reader to complain, and a leaking test will result in complaints
like this (this is a real leak which we have yet to fix):

  $ GIT_TEST_COMMIT_GRAPH=1 make SANITIZE=leak test
  [...]
  Test Summary Report
  -------------------
  t4014-format-patch.sh (Wstat: 256 (exited 1) Tests: 226 Failed: 30)
    Failed tests:  197-226
    Non-zero exit status: 1
    Parse errors: Unknown TAP token: ""
                  Unknown TAP token: "================================================================="
                  Unknown TAP token: "==git==3693658==ERROR: LeakSanitizer: detected memory leaks"
                  Unknown TAP token: ""
                  Unknown TAP token: "Direct leak of 200 byte(s) in 1 object(s) allocated from:"
  Displayed the first 5 of 1531 TAP syntax errors.
  Re-run prove with the -p option to see them all.

You still see the failing tests, so it's mostly just an annoyance. We
can fix it by redirecting to stderr (actually descriptor 4, which is our
verbose-respecting variant). I confirmed manually that the output still
appears with --verbose-log, and even with a single-test "-i
--verbose-only=197" going to the terminal.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agocommit-reach: guard !FIND_ALL early exit with generation ordering check
Kristofer Karlsson [Mon, 29 Jun 2026 13:19:21 +0000 (13:19 +0000)] 
commit-reach: guard !FIND_ALL early exit with generation ordering check

When paint_down_to_common() falls back to commit-date ordering (for
v1 commit graphs without corrected commit dates), the !FIND_ALL early
exit incorrectly fires.  The exit assumes the queue is generation-
ordered, so the first RESULT commit found must be the shallowest.
With date ordering this is not guaranteed: a closer merge base with
a lower committer date (clock skew) may still be in the queue behind
deeper commits.

Add a gen_ordered flag that is cleared when the date fallback fires,
and require it for the early exit.

Update the test from the previous commit to test_expect_success.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agot6600: add test for merge-base early exit with clock skew
Kristofer Karlsson [Mon, 29 Jun 2026 13:19:20 +0000 (13:19 +0000)] 
t6600: add test for merge-base early exit with clock skew

Add a topology where the correct merge base (M2) has a lower
committer date than its ancestor (M1) due to clock skew.  With a
v1 commit graph (topological levels only, no corrected commit
dates), paint_down_to_common() falls back to commit-date ordering.
In that mode, M1 pops before M2, acquires both paint sides, and
the !FIND_ALL early exit fires -- returning the wrong merge base.

Mark the test as test_expect_failure to document the bug; the next
commit will fix it.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agohistory: streamline message preparation and plug file stream leak
Junio C Hamano [Mon, 29 Jun 2026 16:08:42 +0000 (09:08 -0700)] 
history: streamline message preparation and plug file stream leak

An early part of fill_commit_message() function uses write_file_buf()
to write out what was prepared in a strbuf, which is primarily meant
for use by callers that have their own message prepared fully and
called as the last thing to flush it to the destination file.

However, the function then opens a file stream in append mode to
further write into it.  It may have been understandable if this was
a later addition, but it seems it came from a single commit,
d205234c (builtin/history: implement "reword" subcommand,
2026-01-13), which is somewhat puzzling, but anyway...

Just open the file stream upfront for writing, write the message
the function has in the strbuf, and then keep writing whatever it
wants to write to the same open file stream.

And do not forget to close the stream.  We are about to pass the
resulting file to an external editor, and on some systems, notably
Windows, you are not supposed to keep a file open while expecting
another program to access it.

Diagnosed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoGit 2.55 maint v2.55.0
Junio C Hamano [Mon, 29 Jun 2026 14:58:39 +0000 (07:58 -0700)] 
Git 2.55

Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoMerge branch 'jk/t5551-expensive-test-timeouts-fix'
Junio C Hamano [Mon, 29 Jun 2026 14:56:22 +0000 (07:56 -0700)] 
Merge branch 'jk/t5551-expensive-test-timeouts-fix'

The Apache timeout in HTTP tests has been increased to prevent test
failures on heavily loaded CI runners. The tests creating an
enormous number of refs have been isolated to their own repositories
to avoid slowing down subsequent tests.

* jk/t5551-expensive-test-timeouts-fix:
  t5551: put many-tags case into its own repo
  t/lib-httpd: bump apache timeout

3 weeks agot5551: put many-tags case into its own repo
Jeff King [Sun, 28 Jun 2026 08:03:45 +0000 (04:03 -0400)] 
t5551: put many-tags case into its own repo

Most of the t5551 http fetch tests use a handful of refs. But there are
a few test cases which check our handling of large numbers of refs.
These tests use the same server-side repo, so all subsequent tests end
up having to consider those extra refs, too.

The result is that the test script is a bit slower than it needs to be.
In a normal run, moving the "2,000 tags" test into its own repo drops my
runtime for the whole script from ~2.7s to ~1.9s.

This is a modest gain, but when we add the "--long" flag it gets much
bigger. There we trigger a test (marked with EXPENSIVE) that adds
100,000 tags, and the script runtime jumps to ~95s. But if we use the
same "many tags" repo for that, our runtime drops to just ~37s.

This is a pretty easy win to drop the cost of the script. It may even be
a larger gain on a heavily loaded system, since one of the main costs
here is unpacked refs, which are heavy on system time and I/O costs.

It's possible we are reducing test coverage, since all of those other
tests were inadvertently using large ref advertisements (and thus could
have uncovered some unexpected interaction). But that seems somewhat
unlikely; the tests targeted at the large number of refs are doing
roughly similar things to the other tests.

Note that the real performance culprit is the 100k-tag --long test, not
the 2k-tag one. So we could just let the 100k one use its own repo, and
keep the 2k tags in the main repo. But since these two tests are
somewhat interlinked, it's easier to just move them both (and it does
provide a small gain even for the 2000-tag test). I also notice that the
2000-tag test is gated on the CMDLINE_LIMIT prereq, and without that the
later EXPENSIVE test will fail (since we won't have a too-many-refs
clone). Nobody seems to have noticed or complained after many years, and
I left it alone for this patch.

Signed-off-by: Jeff King <peff@peff.net>
[jc: made the new "many-tags.git" bare to match the original "repo.git"]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoMerge branch 'js/http-https-proxy-fix'
Junio C Hamano [Sun, 28 Jun 2026 22:18:24 +0000 (15:18 -0700)] 
Merge branch 'js/http-https-proxy-fix'

We lost ability to use https:// proxies during this cycle; this is
a hotfix for the regression.

* js/http-https-proxy-fix:
  http: accept https:// proxies again

3 weeks agoreftable: fix unlikely leak on API error
Jeff King [Sun, 28 Jun 2026 09:03:14 +0000 (05:03 -0400)] 
reftable: fix unlikely leak on API error

If the reftable writer sees a bogus block size, we return with
REFTABLE_API_ERROR, leaking the reftable_writer struct we previously
allocated. Originally this case was a BUG(), but it became a regular
return in 445f9f4f35 (reftable: stop using `BUG()` in trivial cases,
2025-02-18).

We could obviously fix it by calling "reftable_free(wp)". But we can
observe that we never use the allocated "wp" until after we've validated
the input options. So let's just bump the allocation down. That fixes
the leak, and I think makes the flow of the function more logical
(we validate our inputs before doing any work).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agot/lib-httpd: bump apache timeout
Jeff King [Sun, 28 Jun 2026 08:00:09 +0000 (04:00 -0400)] 
t/lib-httpd: bump apache timeout

Since enabling more tests with 7a094d68a2 (ci: run expensive tests on
push builds to integration branches, 2026-05-08), we sometimes see test
failures or timeouts in GitHub CI. The culprit seems to be the "enormous
ref negotiation" test in t5551, which creates ~100k tag refs in our http
server-side repo.

Iterating through the loose refs of this repo to generate a ref
advertisement can take a long time, especially on a platform with slow
I/O. On my otherwise unloaded local machine, a cold cache ref
advertisement takes ~10s. On a busy CI machine running tests in
parallel, it can presumably top 60s, which runs afoul of Apache's
default CGI timeout.

The result in t5551 is a test failure, where Apache simply hangs up the
connection and the client reports an error. But worse, t5559 runs the
same test with HTTP/2, and a bug in Apache causes the connection to hang
indefinitely! We eventually see this as a CI timeout after 6 hours.

Let's bump Apache's timeout to something much larger: 600 seconds. This
doesn't eliminate the possibility of a timeout, but it makes it much
less likely. It should eliminate both the test failures and the CI
timeouts in practice, and it protects us from running into similar
problems with other tests in the future.

There are two counter-arguments to consider.

One, could/should we just make the test faster? Probably yes. The
biggest mistake here is having such an absurd number of unpacked refs on
a system which is bottle-necked on I/O. But I think it's worth bumping
the timeout so that we can fix this (and possibly other) correctness
issues, and then consider performance separately (which we'll do in
subsequent patches).

And two, is this just papering over a problem that users might see in
the real world? We could teach Git to handle this case more gracefully
with optimizations or keep-alives. But I think it's really an artificial
situation. You need a combination of this silly number of loose refs,
plus a very heavily loaded system. If you were trying to run a real
server and it took more than 60s to generate the ref advertisement, I
don't think the timeout is your biggest problem. Your crappy service is,
and you should adjust your resources to match your load. I.e., it is
probably reasonable for Git to assume that advertisements happen
fast-ish and don't need protocol-level keepalives.

Though the patch here is small, tons of work went into analyzing the
problem. Many thanks to the contributors credited below.

Helped-by: Michael Montalbo <mmontalbo@gmail.com>
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agohttp: accept https:// proxies again
Johannes Schindelin [Sat, 27 Jun 2026 17:17:56 +0000 (17:17 +0000)] 
http: accept https:// proxies again

Since 663d7abe07ea (http: reject unsupported proxy URL schemes,
2026-05-05), set_curl_proxy_type() returns 0 only for the "http"
and SOCKS variants via dedicated early returns, and -1 for
everything else. The "https" branch configures the CURL handle for
HTTPS proxying but then falls through to the trailing `return -1`
intended for unknown schemes, so the caller in get_curl_handle()
treats a perfectly valid https:// proxy URL as unsupported and
refuses to use it.

Noticed while looking into a Coverity report against the same
function; the unchecked curl_easy_setopt() return values it flags
are orthogonal to this fix.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoMerge tag 'l10n-2.55.0-v1' of https://github.com/git-l10n/git-po
Junio C Hamano [Sun, 28 Jun 2026 15:28:08 +0000 (08:28 -0700)] 
Merge tag 'l10n-2.55.0-v1' of https://github.com/git-l10n/git-po

l10n-2.55.0-v1

* tag 'l10n-2.55.0-v1' of https://github.com/git-l10n/git-po:
  l10n: zh-TW.po: Update Chinese (Traditional) translation
  l10n: uk: add 2.55 translation
  l10n: ga.po: update for Git 2.55
  l10n: fr: mass fix of typos
  l10n: fr: version 2.55
  l10n: po-id for 2.55
  l10n: AGENTS.md: add quotation mark preservation guidelines
  l10n: zh_CN: updated translation for 2.55
  l10n: TEAMS: change Simplified Chinese team leader
  l10n: sv.po: Update Swedish translation
  l10n: ca.po: update Catalan translation
  l10n: tr: Update Turkish translations
  l10n: bg.po: Updated Bulgarian translation (6322t)
  l10n: it: fix italian usage messages alignment

3 weeks agoMerge branch '2.55-uk-pr' of github.com:arkid15r/git-ukrainian-l10n
Jiang Xin [Sun, 28 Jun 2026 11:25:08 +0000 (19:25 +0800)] 
Merge branch '2.55-uk-pr' of github.com:arkid15r/git-ukrainian-l10n

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

3 weeks agoMerge branch 'l10n-ga-2.55' of github.com:aindriu80/git-po
Jiang Xin [Sun, 28 Jun 2026 08:49:15 +0000 (16:49 +0800)] 
Merge branch 'l10n-ga-2.55' of github.com:aindriu80/git-po

* 'l10n-ga-2.55' of github.com:aindriu80/git-po:
  l10n: ga.po: update for Git 2.55

3 weeks agoMerge branch 'l10n/zh-TW/2026-06-26' of github.com:l10n-tw/git-po
Jiang Xin [Sun, 28 Jun 2026 08:20:41 +0000 (16:20 +0800)] 
Merge branch 'l10n/zh-TW/2026-06-26' of github.com:l10n-tw/git-po

* 'l10n/zh-TW/2026-06-26' of github.com:l10n-tw/git-po:
  l10n: zh-TW.po: Update Chinese (Traditional) translation

3 weeks agoMerge branch 'ca-20260624-b' of github.com:Softcatala/git-po
Jiang Xin [Sun, 28 Jun 2026 08:17:45 +0000 (16:17 +0800)] 
Merge branch 'ca-20260624-b' of github.com:Softcatala/git-po

* 'ca-20260624-b' of github.com:Softcatala/git-po:
  l10n: ca.po: update Catalan translation

3 weeks agoMerge branch 'zh_CN-2.55' of github.com:lilydjwg/git-po
Jiang Xin [Sun, 28 Jun 2026 08:15:39 +0000 (16:15 +0800)] 
Merge branch 'zh_CN-2.55' of github.com:lilydjwg/git-po

* 'zh_CN-2.55' of github.com:lilydjwg/git-po:
  l10n: zh_CN: updated translation for 2.55
  l10n: TEAMS: change Simplified Chinese team leader

3 weeks agoMerge branch 'tr-l10n' of github.com:bitigchi/git-po
Jiang Xin [Sun, 28 Jun 2026 08:14:13 +0000 (16:14 +0800)] 
Merge branch 'tr-l10n' of github.com:bitigchi/git-po

* 'tr-l10n' of github.com:bitigchi/git-po:
  l10n: tr: Update Turkish translations

3 weeks agoMerge branch 'po-id' of github.com:bagasme/git-po
Jiang Xin [Sun, 28 Jun 2026 08:12:30 +0000 (16:12 +0800)] 
Merge branch 'po-id' of github.com:bagasme/git-po

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

3 weeks agoMerge branch 'master' of github.com:alshopov/git-po
Jiang Xin [Sun, 28 Jun 2026 08:11:24 +0000 (16:11 +0800)] 
Merge branch 'master' of github.com:alshopov/git-po

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

3 weeks agoMerge branch 'fr_v2.55' of github.com:jnavila/git
Jiang Xin [Sun, 28 Jun 2026 08:09:26 +0000 (16:09 +0800)] 
Merge branch 'fr_v2.55' of github.com:jnavila/git

* 'fr_v2.55' of github.com:jnavila/git:
  l10n: fr: mass fix of typos
  l10n: fr: version 2.55

3 weeks agoMerge branch 'master' of github.com:nafmo/git-l10n-sv
Jiang Xin [Sun, 28 Jun 2026 08:07:00 +0000 (16:07 +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

3 weeks agol10n: zh-TW.po: Update Chinese (Traditional) translation
Lumynous [Sat, 20 Jun 2026 11:36:09 +0000 (19:36 +0800)] 
l10n: zh-TW.po: Update Chinese (Traditional) translation

Signed-off-by: Yi-Jyun Pan <pan93412@gmail.com>
3 weeks agopush: suggest <remote> <branch> for a slash slip
Harald Nordgren [Sat, 27 Jun 2026 18:02:25 +0000 (18:02 +0000)] 
push: suggest <remote> <branch> for a slash slip

When pushing the 'main' branch to the remote 'origin', i.e.,

    $ git push origin main

it is easy to mistakenly write

    $ git push origin/main

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

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

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

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

    $ git push origin main

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

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agobranch: suggest <remote>/<branch> on upstream slip
Harald Nordgren [Sat, 27 Jun 2026 18:02:24 +0000 (18:02 +0000)] 
branch: suggest <remote>/<branch> on upstream slip

When setting the upstream of the current branch to the 'main' branch
of the remote 'origin', i.e.,

    $ git branch --set-upstream-to origin/main

it is easy to mistakenly write

    $ git branch --set-upstream-to origin main

That is parsed as a request to set the upstream of the local branch
'main' to 'origin'. When 'main' does not exist, the command dies
with:

    fatal: branch 'main' does not exist

pointing at a branch the user never meant to name. When 'main' does
exist, it instead dies with:

    fatal: the requested upstream branch 'origin' does not exist

leaving the user equally puzzled.

When the operated-on branch is missing and '<remote>/<branch>' names
a real remote-tracking ref, suggest the intended form:

    $ git branch --set-upstream-to=origin/main

The suggestion is gated on '<remote>/<branch>' existing so it only
appears when a slipped slash is the likely explanation.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agot3420-rebase-autostash: don't try to grep non-existing files
SZEDER Gábor [Sun, 10 Oct 2021 17:28:09 +0000 (19:28 +0200)] 
t3420-rebase-autostash: don't try to grep non-existing files

Several tests in 't3420-rebase-autostash.sh' start various rebase
processes that are expected to fail because of merge conflicts.  The
tests [1] checking that 'git rebase --quit' and autostash work
together as expected after such a failure then run '! grep ...' to
ensure that the dirty contents of the file is gone.  However, due to
the test repo's history and the choice of upstream branch that file
shouldn't exist in the conflicted state at all, and thus it shouldn't
exist after the subsequent 'git rebase --quit' either.  Consequently,
this 'grep' doesn't fail as expected, i.e. because it can't find the
dirty content, but instead it fails, because it can't open the file.

Thighten this check by using 'test_path_is_missing' instead, thereby
avoiding unexpected errors from 'grep' as well.

Previously 2745817028 (t3420-rebase-autostash: don't try to grep
non-existing files, 2018-08-22) fixed a couple of similar issues; this
one was added later in 9b2df3e8d0 (rebase: save autostash entry into
stash reflog on --quit, 2020-04-28).

[1] This patch modifies only a single test, but that test is run
    several times with different strategies ('--apply', '--merge', and
    '--interactive'), hence the plural "tests".

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agol10n: uk: add 2.55 translation
Arkadii Yakovets [Sat, 27 Jun 2026 18:42:28 +0000 (11:42 -0700)] 
l10n: uk: add 2.55 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>
3 weeks agol10n: ga.po: update for Git 2.55
Aindriú Mac Giolla Eoin [Sat, 27 Jun 2026 13:41:58 +0000 (14:41 +0100)] 
l10n: ga.po: update for Git 2.55

Signed-off-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
3 weeks agol10n: fr: mass fix of typos
Jean-Noël Avila [Wed, 24 Jun 2026 10:20:45 +0000 (12:20 +0200)] 
l10n: fr: mass fix of typos

Helped-by: Kévin Leprêtre <k.lepretre@houseofhr.onmicrosoft.com>
Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
3 weeks agol10n: fr: version 2.55
Jean-Noël Avila [Sun, 14 Jun 2026 06:18:10 +0000 (08:18 +0200)] 
l10n: fr: version 2.55

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
3 weeks agol10n: po-id for 2.55
Bagas Sanjaya [Sat, 27 Jun 2026 04:00:14 +0000 (11:00 +0700)] 
l10n: po-id for 2.55

Update following components:

  * add-patch.c
  * apply.c
  * bisect.c
  * builtin/add.c
  * builtin/backfill.c
  * builtin/bisect.c
  * builtin/cat-file.c
  * builtin/checkout.c
  * builtin/config.c
  * builtin/fast-import.c
  * builtin/fetch.c
  * builtin/fsmonitor--daemon.c
  * builtin/hook.c
  * builtin/index-pack.c
  * builtin/interpret-trailers.c
  * builtin/last-modified.c
  * builtin/log.c
  * builtin/multi-pack-index.c
  * builtin/name-rev.c
  * builtin/pack-objects.c
  * builtin/push.c
  * builtin/repack.c
  * builtin/replay.c
  * builtin/repo.c
  * builtin/show-index.c
  * builtin/stash.c
  * builtin/submodule--helper.c
  * builtin/worktree.c
  * command-list.h
  * diff.c
  * fetch-pack.c
  * hook.c
  * list-objects-filter-options.c
  * lockfile.c
  * midx-write.c
  * midx.c
  * object-file.c
  * object.c
  * packfile.c
  * path-walk.c
  * pretty.c
  * promisor-remote.c
  * pseudo-merge.c
  * read-cache.c
  * refs.c
  * remote-curl.c
  * repack-midx.c
  * replay.c
  * repository.c
  * revision.c
  * sequencer.c
  * setup.c
  * submodule.c
  * t/helper/test-path-walk.c
  * t/helper/test-read-midx.c
  * trailer.c
  * git-send-email.perl

Translate following new components:

  * builtin/history.c
  * builtin/url-parse.c
  * compat/fsmonitor/fsm-listen-linux.c
  * sideband.c
  * t/helper/test-synthesize.c

Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com>
3 weeks agorefs: protect against chicken-and-egg recursion
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:09 +0000 (11:20 +0200)] 
refs: protect against chicken-and-egg recursion

In the preceding commits we have fixed recursion when creating the
reference backends due to a chicken-and-egg situation with "onbranch"
conditions. Unfortunately, this issue has existed for a while, and we
didn't really have a good mechanism to detect this recursion.

Improve the status quo by detecting the recursion when creating the main
reference store.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agorefs/reftable: lazy-load configuration to fix chicken-and-egg
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:08 +0000 (11:20 +0200)] 
refs/reftable: lazy-load configuration to fix chicken-and-egg

Same as with the "files" backend, the "reftable" backend also has a
chicken-and-egg problem with "onbranch" conditions. Fix this issue the
same as we did with the "files" backend by lazy-loading configuration.

Now that both the "files" and the "reftable" backend handle this
properly, add a generic test to t1400 that verifies that the user can
configure "core.logAllRefUpdates" via an "onbranch" condition. This is
mostly a nonsensical thing to do in the first place, but it serves as a
good sanity check.

Note that we had to move `should_write_log()` around so that it can
access the new `reftable_be_write_options()` function.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoreftable: split up write options
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:07 +0000 (11:20 +0200)] 
reftable: split up write options

When initializing the reftable stack the caller may optionally pass some
write options. These write options mix up two different concerns though:

  - Of course, they allow the caller to configure how new reftables are
    being written.

  - But they also allow the caller to configure the stack itself, like
    its hash ID and the `on_reload` callback.

This is somewhat awkward, as it doesn't easily give the caller the
flexibility to for example write multiple reftables with different
options. Furthermore, this requires us to eagerly parse relevant
configuration when initializing the reftable backend.

Refactor the code by splitting out those options that configure the
stack itself. Creating a new stack will thus only require this limited
set of options, whereas the caller is expected to pass write options to
all functions that end up writing tables.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agorefs/files: lazy-load configuration to fix chicken-and-egg
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:06 +0000 (11:20 +0200)] 
refs/files: lazy-load configuration to fix chicken-and-egg

When initializing the "files" reference backend we read the repository's
config to parse "core.preferSymlinkRefs" and "core.logAllRefUpdates".
This results in a chicken-and-egg problem though, because parsing the
configuration may require us to have access to the reference store
already when an "onbranch" condition exists.

Luckily, all the configuration that we honor only relates to writing
references. Consequently, we don't strictly need that configuration to
be readily available at initialization time, and we can easiliy defer
parsing it to a later point in time.

Implement this fix and add tests that verify that we can indeed properly
parse these config knobs via an "onbranch" condition.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agorefs: move parsing of "core.logAllRefUpdates" back into ref stores
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:05 +0000 (11:20 +0200)] 
refs: move parsing of "core.logAllRefUpdates" back into ref stores

In cc42c88945 (refs: extract out reflog config to generic layer,
2026-05-04) we have refactored how we parse "core.logAllRefUpdates" so
that it happens in the generic layer. Unfortunately, this has worsened a
preexisting issue where we may recurse when creating the reference store
because of a chicken-and-egg problem between parsing the configuration
and evaluating "onbranch" conditions.

Prepare for a fix by essentially reverting that change so that we handle
this setting in the respective backends again. The backends are already
parsing other configuration anyway, so by moving the logic back in there
we can ensure that all backend configuration is parsed the same way.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agorepository: free main reference database
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:04 +0000 (11:20 +0200)] 
repository: free main reference database

While we release worktree and submodule reference databases when
clearing a repository, we don't ever release the main reference
database. This memory leak went unnoticed because its pointer is
kept alive by the "chdir_notify" subsystem.

Fix the memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agochdir-notify: drop unused `chdir_notify_reparent()`
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:03 +0000 (11:20 +0200)] 
chdir-notify: drop unused `chdir_notify_reparent()`

With the preceding commit we've removed all callers of
`chdir_notify_reparent()`, so the function is unused now. Drop it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agorefs: unregister reference stores from "chdir_notify"
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:02 +0000 (11:20 +0200)] 
refs: unregister reference stores from "chdir_notify"

When creating reference stores we register them with the "chdir_notify"
subsystem. This is required because some of the paths we track may be
relative paths, so we have to reparent them in case the current working
directory changes.

But while we register the reference stores, we never unregister them.
This can have multiple outcomes:

  - For a repository's main reference database we essentially keep the
    pointer alive. We never free that database, either, and our leak
    checker doesn't notice because it's still registered.

  - For submodule and worktree reference databases we do eventually free
    them in `repo_clear()`, so we may keep pointers to free'd memory
    registered. We never notice though as we don't tend to chdir around
    in the middle of the process.

We never noticed either of these symptoms, but they are obviously bad.

Partially fix those issues by unregistering the reference stores when
releasing them. The leak of the main reference database will be fixed in
a subsequent commit.

Note that this requires us to use `chdir_notify_register()` instead of
`chdir_notify_reparent()`, as there is no infrastructure to unregister the
latter.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agosetup: don't apply "GIT_REFERENCE_BACKEND" without a repository
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:01 +0000 (11:20 +0200)] 
setup: don't apply "GIT_REFERENCE_BACKEND" without a repository

When discovering a repository we eventually also apply the
"GIT_REFERENCE_BACKEND" environment variable to the repository. There's
two problems with that:

  - We do this unconditionally, which is rather pointless: we really
    only have to configure the repository when we have found one.

  - We have already applied the repository format at that point in time,
    so we need to manually reapply it.

Move the logic around so that we only apply the environment variable
when a repository was discovered. This also allows us to drop the
explcit call to `repo_set_ref_storage_format()` because we now adjust
the format before we apply it via `apply_repository_format()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agosetup: stop applying repository format twice
Patrick Steinhardt [Thu, 25 Jun 2026 09:20:00 +0000 (11:20 +0200)] 
setup: stop applying repository format twice

When discovering the repository in "setup.c" we apply the final
repository format multiple times:

  - Once via `repository_format_configure()`, where we apply the hash
    algorithm and ref storage format to both `struct repository_format`
    and `struct repository`.

  - And once via `apply_repository_format()`, where we apply these two
    settings from `struct repository_format` to `struct repository`.

With the current flow both of these are in fact necessary. But this is
only because we call `repository_format_configure()` after we have
called `apply_repository_format()`. Consequently, if we only changed the
repository format in `repository_format_configure()` it would never
propagate to the repository.

Refactor the code so that we first configure the repository format
before applying it to the repository so that we can stop setting the
hash and reference storage format multiple times.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agosetup: inline `check_and_apply_repository_format()`
Patrick Steinhardt [Thu, 25 Jun 2026 09:19:59 +0000 (11:19 +0200)] 
setup: inline `check_and_apply_repository_format()`

We have two callsites of `check_and_apply_repository_format()`. In a
subsequent commit we'll want to adapt one of those callsites to change
the order in which we read and apply the repository format, at which
point the helper function will not really be a good fit for us anymore.

Inline the function to both of the callsites.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoMerge branch 'ps/setup-centralize-odb-creation' into ps/refs-onbranch-fixes
Junio C Hamano [Thu, 11 Jun 2026 12:09:19 +0000 (05:09 -0700)] 
Merge branch 'ps/setup-centralize-odb-creation' into ps/refs-onbranch-fixes

* ps/setup-centralize-odb-creation:
  setup: construct object database in `apply_repository_format()`
  repository: stop reading loose object map twice on repo init
  setup: stop initializing object database without repository
  setup: stop creating the object database in `setup_git_env()`
  repository: stop initializing the object database in `repo_set_gitdir()`
  setup: deduplicate logic to apply repository format
  setup: drop `setup_git_env()`
  t0001: plug test gaps for git-init(1) with GIT_OBJECT_DIRECTORY

3 weeks agoMerge branch 'master' of github.com:mbeniamino/git-po
Jiang Xin [Fri, 26 Jun 2026 12:51:39 +0000 (20:51 +0800)] 
Merge branch 'master' of github.com:mbeniamino/git-po

* 'master' of github.com:mbeniamino/git-po:
  l10n: it: fix italian usage messages alignment

3 weeks agol10n: AGENTS.md: add quotation mark preservation guidelines
Jiang Xin [Fri, 26 Jun 2026 11:57:52 +0000 (19:57 +0800)] 
l10n: AGENTS.md: add quotation mark preservation guidelines

Add a "Preserving Quotation Marks" section to prevent AI-assisted
translation and review from incorrectly converting language-specific
UTF-8 curly quotes (e.g., â€ž U+201E, " U+201C for Bulgarian) into
ASCII straight quotes " (U+0022), which would cause PO string
truncation and syntax errors.

Also update the "Special characters" item in the Quality checklist
to reference the new section.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
3 weeks agol10n: zh_CN: updated translation for 2.55
lilydjwg [Sun, 21 Jun 2026 08:16:11 +0000 (16:16 +0800)] 
l10n: zh_CN: updated translation for 2.55

Reviewed-by: Jiang Xin <worldhello.net@gmail.com>
Reviewed-by: Fangyi Zhou <me@fangyi.io>
Signed-off-by: lilydjwg <lilydjwg@gmail.com>
3 weeks agol10n: TEAMS: change Simplified Chinese team leader
lilydjwg [Mon, 22 Jun 2026 06:20:21 +0000 (14:20 +0800)] 
l10n: TEAMS: change Simplified Chinese team leader

Signed-off-by: lilydjwg <lilydjwg@gmail.com>
3 weeks agoMerge branch 'ps/t4216-tap-fix'
Junio C Hamano [Fri, 26 Jun 2026 02:49:01 +0000 (19:49 -0700)] 
Merge branch 'ps/t4216-tap-fix'

TAP output breakage fix.

* ps/t4216-tap-fix:
  t4216: fix no-op test that breaks TAP output

3 weeks agoconnected: search promisor objects generically
Patrick Steinhardt [Thu, 25 Jun 2026 09:57:42 +0000 (11:57 +0200)] 
connected: search promisor objects generically

When performing connectivity checks we have to figure out whether any of
the new objects are promisor objects, as we cannot assume full
connectivity if so.

This check is performed by iterating through all packfiles in the
repository and searching each of them for the given object. Of course,
this mechanism is quite specific to implementation details of the object
database, as we assume that it uses packfiles in the first place.

Refactor the logic so that we instead use `odb_for_each_object_ext()`
with an object prefix filter and the `ODB_FOR_EACH_OBJECT_PROMISOR_ONLY`
flag. This will yield all objects that have the exact object name and
that are part of a promisor pack in a generic way.

Add a test to verify that we indeed use the optimization.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoconnected: split out promisor-based connectivity check
Patrick Steinhardt [Thu, 25 Jun 2026 09:57:41 +0000 (11:57 +0200)] 
connected: split out promisor-based connectivity check

When performing a connectivity check in a partial clone we try to avoid
doing the connectivity check by checking whether all new tips are part
of a promisor pack. This makes use of the fact that we don't expect full
connectivity for promised objects anyway, so it's basically fine if
those objects are not fully connected.

The logic that handles this promisor-based check is somewhat hard to
read though as it uses nested loops and gotos. Pull it out into a
standalone function, which makes it a bit easier to reason about.

We'll also further simplify the function in the next commit.

Suggested-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoodb/source-packed: support flags when iterating an object prefix
Patrick Steinhardt [Thu, 25 Jun 2026 09:57:40 +0000 (11:57 +0200)] 
odb/source-packed: support flags when iterating an object prefix

Callers of `odb_for_each_object()` can specify an optional object name
prefix so that we only yield objects that match it. This is incompatible
though with passing flags at the same time, as we don't yet know to
handle them.

Loosen this restriction by calling `should_exclude_pack()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agoodb/source-packed: extract logic to skip certain packs
Patrick Steinhardt [Thu, 25 Jun 2026 09:57:39 +0000 (11:57 +0200)] 
odb/source-packed: extract logic to skip certain packs

The caller can pass flags that allow them to filter out specific kinds
of objects when iterating objects via `odb_for_each_object()`. This only
works for "normal" iteration though, as we `BUG()` when the user passes
flags and specifies an object prefix.

This limitation will be lifted in the next commit. Prepare for this by
extracting the logic that skips certain kinds of packs so that we can
easily reuse it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agot4216: fix no-op test that breaks TAP output
Patrick Steinhardt [Fri, 19 Jun 2026 07:20:20 +0000 (09:20 +0200)] 
t4216: fix no-op test that breaks TAP output

In t4216 we have have a prerequisite that is active in case the system's
`char` type is signed by default. This prerequisite isn't really used by
anything though: while it is used to guard one of our tests, that
specific test is essentially a no-op. So all this infrastructure does is
to provide some debugging hint to a reader that pays a lot of attention.

Besides that, the way we set up the prerequisite also results in broken
TAP output on systems where `char` is unsigned by default: we use
`test_cmp()` to diff two files outside of of any test body, and if the
files differ we enable the prerequisite. If so, the call to `test_cmp()`
would also print output, and that output is of course not valid TAP
output.

That wasn't a problem before 389c83025d (t: let prove fail when parsing
invalid TAP output, 2026-06-04), because our TAP parser was configured
to be lenient. But starting with that commit, t4216 is now failing on
systems with unsigned chars.

Drop the whole infrastructure. The prerequisite is not used anywhere
else, and the only location where it's used doesn't really provide much
value.

Reported-by: Todd Zullinger <tmz@pobox.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Tested-by: Todd Zullinger <tmz@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 weeks agol10n: sv.po: Update Swedish translation
Peter Krefting [Thu, 25 Jun 2026 15:16:10 +0000 (16:16 +0100)] 
l10n: sv.po: Update Swedish translation

Reviewed-by: Tuomas Ahola <taahol@utu.fi>
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
3 weeks agol10n: ca.po: update Catalan translation
Mikel Forcada [Thu, 25 Jun 2026 08:14:24 +0000 (10:14 +0200)] 
l10n: ca.po: update Catalan translation

Signed-off-by: Mikel Forcada <mlf@prompsit.com>
3 weeks agoMerge branch 'ps/odb-source-packed' into ps/odb-drop-whence
Junio C Hamano [Wed, 24 Jun 2026 17:12:12 +0000 (10:12 -0700)] 
Merge branch 'ps/odb-source-packed' into ps/odb-drop-whence

* ps/odb-source-packed:
  odb/source-packed: drop pointer to "files" parent source
  midx: refactor interfaces to work on "packed" source
  odb/source-packed: stub out remaining functions
  odb/source-packed: wire up `freshen_object()` callback
  odb/source-packed: wire up `find_abbrev_len()` callback
  odb/source-packed: wire up `count_objects()` callback
  odb/source-packed: wire up `for_each_object()` callback
  odb/source-packed: wire up `read_object_stream()` callback
  odb/source-packed: wire up `read_object_info()` callback
  packfile: use higher-level interface to implement `has_object_pack()`
  odb/source-packed: wire up `reprepare()` callback
  odb/source-packed: wire up `close()` callback
  odb/source-packed: start converting to a proper `struct odb_source`
  odb/source-packed: store pointer to "files" instead of generic source
  packfile: move packed source into "odb/" subsystem
  packfile: split out packfile list logic
  packfile: rename `struct packfile_store` to `odb_source_packed`

3 weeks agogpg-interface: fix strip_cr_before_lf to only remove CR before LF
Antonio De Stefani [Wed, 24 Jun 2026 09:36:18 +0000 (11:36 +0200)] 
gpg-interface: fix strip_cr_before_lf to only remove CR before LF

c4adea82c5 (Convert CR/LF to LF in tag signatures, 2008-07-11)
introduced CR stripping for GPG output on Windows, but intentionally
stripped all CR characters unconditionally to "keep the code
simpler", even though only CRLF sequences (Windows line endings)
needed to be normalized.

Later 2f47eae2a1 (Split GPG interface into its own helper library,
2011-09-07) moved the code into gpg-interface.c, and 29b315778e (ssh
signing: add ssh key format and signing code, 2021-09-10) extracted
it into the remove_cr_after() helper when adding SSH signing
support, while noticing that it unconditionally strips all CRs,
leaving a NEEDSWORK comment.

Fix the loop to skip CR only when immediately followed by LF,
keeping lone trailing CR characters intact.  Rename the function to
strip_cr_before_lf to reflect its corrected behavior, and update
both call sites and their comments accordingly.

Signed-off-by: Antonio De Stefani <antonio.destefani08@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agol10n: tr: Update Turkish translations
Emir SARI [Tue, 16 Jun 2026 17:41:01 +0000 (20:41 +0300)] 
l10n: tr: Update Turkish translations

Signed-off-by: Emir SARI <emir_sari@icloud.com>
4 weeks agol10n: bg.po: Updated Bulgarian translation (6322t)
Alexander Shopov [Sun, 14 Jun 2026 11:27:13 +0000 (13:27 +0200)] 
l10n: bg.po: Updated Bulgarian translation (6322t)

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
4 weeks agorepo: add path.gitdir with absolute and relative suffix formatting
K Jayatheerth [Wed, 24 Jun 2026 03:37:48 +0000 (09:07 +0530)] 
repo: add path.gitdir with absolute and relative suffix formatting

Scripts need a stable way to locate the git directory without
parsing rev-parse output or relying on its flag-driven path format
selection. There is no way to retrieve this path from git repo info
today.

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

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agorepo: add path.commondir with absolute and relative suffix formatting
K Jayatheerth [Wed, 24 Jun 2026 03:37:47 +0000 (09:07 +0530)] 
repo: add path.commondir with absolute and relative suffix formatting

Scripts working with worktree setups need a reliable way to discover
the common directory, which diverges from the git directory when
multiple worktrees are in use. There is no way to retrieve this path
from git repo info today.

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

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agopath: extract format_path() and use in rev-parse
K Jayatheerth [Wed, 24 Jun 2026 03:37:46 +0000 (09:07 +0530)] 
path: extract format_path() and use in rev-parse

Path formatting logic in builtin/rev-parse.c writes directly to
stdout. Other builtins cannot reuse it.

Extract this logic into format_path() in path.c and expose
a path_format enum in path.h.

Convert rev-parse to use the new helper in the same step to validate
the API against existing tests and avoid introducing dead code.

Mentored-by: Justin Tobler <jltobler@gmail.com>
Mentored-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agostatus: improve rebase todo list parsing
Phillip Wood [Tue, 23 Jun 2026 15:53:57 +0000 (16:53 +0100)] 
status: improve rebase todo list parsing

When there is rebase in progress "git status" displays the last couple
of completed and the next couple of pending commands from the todo
list. When it does this it tries to abbreviate the object ids of
the commits to be picked. Unfortunately it does not abbreviate the
object ids when the line starts with "fixup -C" or "merge -C". It
also mistakenly replaces the refname in "reset main" and "update-ref
refs/heads/main" with the object id that the ref points to.

Fix this by using the function added in the last commit to parse the
command name and only try to abbreviate the argument for commands that
take an object id. If a command accepts a label then try to resolve the
object name as a label first and only if that fails try to resolve it
as an object_id. When trying to abbreviate an object id, only replace
the object name if it starts with the abbreviated object id so that
tag or branch names that contain only hex digits are left unchanged.

Comments are now processed after stripping any leading
whitespace from the line. This matches what the sequencer does in
parse_insn_line(). The existing test cases are updated to test a
wider variety of commands. Only the pending commands in the tests
are changed to avoid removing existing coverage.

Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agosequencer: factor out parsing of todo commands
Phillip Wood [Tue, 23 Jun 2026 15:53:56 +0000 (16:53 +0100)] 
sequencer: factor out parsing of todo commands

Move the code that parses todo commands into a separate function so
that it can be shared with "git status" in the next commit. As we
know the input is NUL terminated we do not pass a pointer to the end
of the line and instead test for a blank line by looking for NUL, CR
LF, or LF. We use starts_with() instead of starts_with_mem() for the
same reason. This results in slightly different behavior when there
a CR at the start of the line that is not followed by LF. Previously
such a line was treated as a comment rather than an invalid line.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agogit-gui: allow larger width for the commit message field
Alexander Shopov [Fri, 19 Jun 2026 15:12:57 +0000 (17:12 +0200)] 
git-gui: allow larger width for the commit message field

Users may like to make the main window very wide. In this case, a rather
small size of the commit message field leaves a wide unused space at the
bottom-right. Allow settting the field width to values much larger than
99 characters. In fact, users can set it to extreme values to fill the
entire space regardless of window width: the widget geometry will be
negotiated to be limited to the available space despite the large
requested width.

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
4 weeks agogitk: make "make -s" silent
Harald Nordgren [Sun, 21 Jun 2026 14:56:42 +0000 (14:56 +0000)] 
gitk: make "make -s" silent

The catalog rule runs msgfmt with --statistics, whose output goes to
stderr and so survives "make -s", and the rule also echoes "Generating
catalog". The Gitk Makefile guards its quiet helpers on V alone, so a
silent build still prints these and the GEN line.

The statistics are not needed, as in 2f12b31b746c (Makefile: don't
invoke msgfmt with --statistics, 2021-12-17). Drop them, suppress the
quiet helpers when "s" is among the make flags, and give the catalog
rule a quiet prefix so a quiet build stays quiet.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
4 weeks agoGit 2.55-rc2 v2.55.0-rc2
Junio C Hamano [Tue, 23 Jun 2026 03:04:38 +0000 (20:04 -0700)] 
Git 2.55-rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoMerge branch 'hn/macos-linker-warning'
Junio C Hamano [Tue, 23 Jun 2026 03:05:04 +0000 (20:05 -0700)] 
Merge branch 'hn/macos-linker-warning'

Xcode 15 and later has a linker set to complain when the same library
archive is listed twice on the command line.  Squelch the annoyance.

* hn/macos-linker-warning:
  config.mak.uname: avoid macOS dup-library warning

4 weeks agoMerge branch 'js/win32-localtime-r'
Junio C Hamano [Tue, 23 Jun 2026 03:05:03 +0000 (20:05 -0700)] 
Merge branch 'js/win32-localtime-r'

Build-fix for 32-bit Windows.

* js/win32-localtime-r:
  win32: ensure that `localtime_r()` is declared even in i686 builds

4 weeks agoMerge branch 'ps/gitlab-ci-windows'
Junio C Hamano [Tue, 23 Jun 2026 03:05:03 +0000 (20:05 -0700)] 
Merge branch 'ps/gitlab-ci-windows'

Wean the Windows builds in GitLab CI procedure away from
(unfortunately unreliable) Chocolatey to install dependencies.

* ps/gitlab-ci-windows:
  gitlab-ci: migrate Windows builds away from Chocolatey

4 weeks agoMerge branch 'ps/odb-source-packed' into ps/connected-generic-promisor-checks
Junio C Hamano [Mon, 22 Jun 2026 17:43:15 +0000 (10:43 -0700)] 
Merge branch 'ps/odb-source-packed' into ps/connected-generic-promisor-checks

* ps/odb-source-packed:
  odb/source-packed: drop pointer to "files" parent source
  midx: refactor interfaces to work on "packed" source
  odb/source-packed: stub out remaining functions
  odb/source-packed: wire up `freshen_object()` callback
  odb/source-packed: wire up `find_abbrev_len()` callback
  odb/source-packed: wire up `count_objects()` callback
  odb/source-packed: wire up `for_each_object()` callback
  odb/source-packed: wire up `read_object_stream()` callback
  odb/source-packed: wire up `read_object_info()` callback
  packfile: use higher-level interface to implement `has_object_pack()`
  odb/source-packed: wire up `reprepare()` callback
  odb/source-packed: wire up `close()` callback
  odb/source-packed: start converting to a proper `struct odb_source`
  odb/source-packed: store pointer to "files" instead of generic source
  packfile: move packed source into "odb/" subsystem
  packfile: split out packfile list logic
  packfile: rename `struct packfile_store` to `odb_source_packed`

4 weeks agoodb: introduce `odb_prepare()`
Patrick Steinhardt [Mon, 22 Jun 2026 08:47:55 +0000 (10:47 +0200)] 
odb: introduce `odb_prepare()`

Introduce `odb_prepare()` as a simple wrapper to prepare alternates and
then prepare each individual source. Adapt git-grep(1) to use it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoodb/source: generalize `reprepare()` callback
Patrick Steinhardt [Mon, 22 Jun 2026 08:47:54 +0000 (10:47 +0200)] 
odb/source: generalize `reprepare()` callback

The `reprepare()` callback function can be used to flush caches of a
given object source and then prepare it anew. This is for example used
when a concurrent process may have written new objects. Ultimately, this
can be seen as doing two separate steps:

  1. We drop any caches.

  2. We prepare the source.

We have one callsite in git-grep(1) though that really only want to do
(2). This is done by reaching into the "files" backend directly and then
calling `odb_source_packed_prepare()`, which of course may not work with
alternate backends.

We could in theory just call `reprepare()` here, and that would likely
not have any significant downside. But this would certainly feel like a
code smell.

Instead, generalize the `reprepare()` callback to `prepare()` with a
flag that optionally instructs the backend to also flush the caches,
which allows us to drop the external `odb_source_packed_prepare()`
declaration.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoMerge branch 'ps/odb-source-packed' into ps/odb-generalize-prepare
Junio C Hamano [Mon, 22 Jun 2026 17:40:01 +0000 (10:40 -0700)] 
Merge branch 'ps/odb-source-packed' into ps/odb-generalize-prepare

* ps/odb-source-packed:
  odb/source-packed: drop pointer to "files" parent source
  midx: refactor interfaces to work on "packed" source
  odb/source-packed: stub out remaining functions
  odb/source-packed: wire up `freshen_object()` callback
  odb/source-packed: wire up `find_abbrev_len()` callback
  odb/source-packed: wire up `count_objects()` callback
  odb/source-packed: wire up `for_each_object()` callback
  odb/source-packed: wire up `read_object_stream()` callback
  odb/source-packed: wire up `read_object_info()` callback
  packfile: use higher-level interface to implement `has_object_pack()`
  odb/source-packed: wire up `reprepare()` callback
  odb/source-packed: wire up `close()` callback
  odb/source-packed: start converting to a proper `struct odb_source`
  odb/source-packed: store pointer to "files" instead of generic source
  packfile: move packed source into "odb/" subsystem
  packfile: split out packfile list logic
  packfile: rename `struct packfile_store` to `odb_source_packed`

4 weeks agowin32: ensure that `localtime_r()` is declared even in i686 builds
Johannes Schindelin [Mon, 22 Jun 2026 08:44:06 +0000 (08:44 +0000)] 
win32: ensure that `localtime_r()` is declared even in i686 builds

The `__MINGW64__` constant is defined, surprise, surprise, only when
building for a 64-bit CPU architecture.

Therefore using it as a guard to define `_POSIX_C_SOURCE` (so that
`localtime_r()` is declared, among other functions) is not enough, we
also need to check `__MINGW32__`.

Technically, the latter constant is defined even for 64-bit builds. But
let's make things a bit easier to understand by testing for both
constants.

Making it so fixes this compile warning (turned error in GCC v14.1):

  archive-zip.c: In function 'dos_time':
  archive-zip.c:612:9: error: implicit declaration of function 'localtime_r';
  did you mean 'localtime_s'? [-Wimplicit-function-declaration]
    612 |         localtime_r(&time, &tm);
        |         ^~~~~~~~~~~
        |         localtime_s

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agolog: improve --follow following renames for non-linear history
Miklos Vajna [Mon, 22 Jun 2026 06:23:31 +0000 (08:23 +0200)] 
log: improve --follow following renames for non-linear history

Have a repo with a subtree merge, do a 'git log --follow prefix/test.c',
the output only contains history in the outer repo, not commits that
were merged via a subtree merge.

What happens is that 'git log --follow' stores the followed path only in
opt->diffopt.pathspec, so in case the commit history is non-linear, and
multiple parents have renames to the followed path, then the end result
isn't really defined: the first commit that happens to be visited in one
of the parents update opt->diffopt.pathspec, and from that point, only
that updated path is visited.

Fix the problem by introducing a commit -> path map
(follow_pathspec_slab) that stores what will be a path to follow when
visiting that parent. At the top of log_tree_commit(), if the slab has
an entry for this commit, we replace opt->diffopt.pathspec with a path
from this entry, so the correct path is followed, even if an unrelated
sub-tree changed the path to be followed to something else. After
log_tree_diff() runs, we record each parent's path in the slab. As a
result, the walk order doesn't matter, which was exactly the source of
problems previously.

This helps with subtree merges (rename happens inside the merge commit),
but also fixes the general case when the rename happens in the history
of parents, not in the merge commit itself.

Signed-off-by: Miklos Vajna <vmiklos@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoA few more topics before -rc2
Junio C Hamano [Sun, 21 Jun 2026 23:41:10 +0000 (16:41 -0700)] 
A few more topics before -rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoMerge branch 'js/objects-larger-than-4gb-on-windows-more'
Junio C Hamano [Sun, 21 Jun 2026 23:41:37 +0000 (16:41 -0700)] 
Merge branch 'js/objects-larger-than-4gb-on-windows-more'

* js/objects-larger-than-4gb-on-windows-more:
  odb: use size_t for object_info.sizep and the size APIs
  packfile,delta: drop the `cast_size_t_to_ulong()` wrappers
  pack-objects: use size_t for in-core object sizes
  packfile: widen unpack_entry()'s size out-parameter to size_t
  pack-objects(check_pack_inflate()): use size_t instead of unsigned long
  patch-delta: use size_t for sizes
  compat/msvc: use _chsize_s for ftruncate

4 weeks agoMerge branch 'kw/gitattributes-typofix'
Junio C Hamano [Sun, 21 Jun 2026 23:41:37 +0000 (16:41 -0700)] 
Merge branch 'kw/gitattributes-typofix'

* kw/gitattributes-typofix:
  gitattributes: fix eol attribute for Perl scripts

4 weeks agopack-objects: support `--delta-islands` with `--path-walk`
Taylor Blau [Sun, 21 Jun 2026 23:03:10 +0000 (19:03 -0400)] 
pack-objects: support `--delta-islands` with `--path-walk`

Since the inception of `--path-walk`, this option has had a documented
incompatibility with `--delta-islands`.

When discussing those original patches on the list, a message from
Stolee in [1] noted the following:

    this could be remedied by [...] doing a separate walk to identify
    islands using the normal method

In a related portion of the thread, Peff explains[2]:

    The delta islands code already does its own tree walk to propagate
    the bits down (it does rely on the base walk's show_commit() to
    propagate through the commits).

    Once each object has its island bitmaps, I think however you
    choose to come up with delta candidates [...] you should be able
    to use it. It's fundamentally just answering the question of "am
    I allowed to delta between these two objects".

That is similar to what this patch does, and it turns out the cheaper
option is sufficient: perform the same island side effects from the
path-walk callback rather than doing a second walk.

Recall how delta-islands are computed during a normal repack:

 - `show_commit()` calls `propagate_island_marks()` for each commit,
   which merges the commit's island bitset onto its root tree object and
   onto each of its parent commits.

 - `show_object()` for a tree records the tree's depth derived from the
   slash-separated pathname. Subsequent `resolve_tree_islands()` uses
   that depth to walk trees in increasing-depth order, propagating each
   tree's marks to its children.

 - At delta-search time, `in_same_island()` enforces that a delta
   target's island bitmap is a subset of its base's: every island that
   reaches the target must also reach the base.

Path-walk's enumeration callback is `add_objects_by_path()`. It already
adds objects to `to_pack`, but until now did not perform the
island-related side effects. Two things are needed:

 - For each commit batch, call `propagate_island_marks()` on commits,
   exactly as `show_commit()` does.

   We have to be careful about the order in which we call this function,
   and we must see a commit before its parents in order to have
   island marks to propagate.

   The path-walk batch preserves that order. Path-walk appends commits
   to its `OBJ_COMMIT` batch as they come back from the same
   `get_revision()` loop the regular traversal uses, and
   `add_objects_by_path()` iterates the batch in array order. So every
   commit reaches `propagate_island_marks()` in the same sequence that
   `show_commit()` would have seen it, and the descendant-first chain
   that the algorithm relies on is intact.

   Skip island propagation for excluded commits to match the regular
   traversal, whose `show_commit()` callback is only invoked for
   interesting commits. Boundary commits may still be present in
   path-walk's callback so they can serve as thin-pack bases, but they
   should not contribute island marks.

 - For each tree batch, record the tree's depth from the path. Use the
   `record_tree_depth()` helper from the previous commit so both
   callbacks behave identically, including the max-depth-wins behavior
   when a tree is reached via more than one path. The helper accepts
   both the `show_object()` path shape ("foo", "foo/bar") and the
   path-walk shape with a trailing slash ("foo/", "foo/bar/"), so depths
   recorded from either traversal mode are directly comparable.

   This is implicit in the implementation sketch from Peff above.
   `resolve_tree_islands()` sorts trees by `oe->tree_depth` in
   increasing-depth order before propagating marks down, so that a
   parent tree's marks are finalized before its children inherit them.
   Without recording the depth at path-walk time, every
   path-walk-discovered tree would land at depth 0 in `to_pack`, the
   sort would lose its ordering, and children could inherit marks from
   parents whose own contributions had not yet been merged in.

With those two pieces in place, `resolve_tree_islands()` receives the
same island inputs from path-walk as it would from the regular
traversal, so the existing island checks can be reused unchanged.

Drop the documented incompatibility between `--path-walk` and
`--delta-islands`, and add t5320 coverage for path-walk island repacks
with and without bitmap writing, as well as the same-island case where a
delta remains allowed.

[1]: https://lore.kernel.org/git/9aa2471b-0850-4707-9733-d3b33609f5f2@gmail.com/
[2]: https://lore.kernel.org/git/20240911063203.GA1538586@coredump.intra.peff.net/

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agopack-objects: extract `record_tree_depth()` helper
Taylor Blau [Sun, 21 Jun 2026 23:03:07 +0000 (19:03 -0400)] 
pack-objects: extract `record_tree_depth()` helper

Prepare for a subsequent change that needs to record tree depths from a
second call site by factoring the delta-islands tree-depth bookkeeping
out of `show_object()` and into a helper, `record_tree_depth()`.

The helper looks up the object in `to_pack`, returns early when the
object was not added there, computes the depth from the slash count in
the supplied name, and preserves the existing max-depth-wins behavior
when a tree is reached by more than one path.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agopack-objects: support reachability bitmaps with `--path-walk`
Taylor Blau [Sun, 21 Jun 2026 23:03:03 +0000 (19:03 -0400)] 
pack-objects: support reachability bitmaps with `--path-walk`

When 'pack-objects' is invoked with '--path-walk', it prevents us from
using reachability bitmaps.

This behavior dates back to 70664d2865c (pack-objects: add --path-walk
option, 2025-05-16), which included a comment in the relevant portion of
the command-line arguments handling that read as follows:

    /*
     * We must disable the bitmaps because we are removing
     * the --objects / --objects-edge[-aggressive] options.
     */

In fb2c309b7d3 (pack-objects: pass --objects with --path-walk,
2026-05-02), path-walk learned to pass '--objects' again, but still
kept bitmap traversal disabled. That leaves two useful cases
unsupported:

 * A path-walk repack that writes bitmaps does not give the bitmap
   selector any commits, because path-walk reveals commits through
   `add_objects_by_path()` rather than through `show_commit()`, where
   `index_commit_for_bitmap()` is normally called.

 * An invocation like "git pack-objects --use-bitmap-index --path-walk"
   never tries an existing bitmap, even when one is available and could
   answer the request.

Fortunately for us, neither restriction is required.

 * On the writing side: teach the path-walk object callback to call
   `index_commit_for_bitmap()` for commits that it adds to the pack.
   That gives the bitmap selector the commit candidates it would have
   seen from the regular traversal.

 * For bitmap reading, keep passing '--objects' to the internal rev_list
   machinery, but stop clearing `use_bitmap_index`. If an existing
   bitmap can answer the request, use it; otherwise fall back to
   path-walk's own enumeration.

As a result, we can see significantly reduced pack generation times from
p5311 (with our `GIT_PERF_REPO` set to a recent clone of the fluentui
repository) before this commit:

    Test                                            HEAD^             HEAD
    ----------------------------------------------------------------------------------------
    5311.40: server (1 days, --path-walk)           1.43(1.39+0.04)   0.01(0.01+0.00) -99.3%
    5311.41: size   (1 days, --path-walk)                    139.6K            139.7K +0.0%
    5311.42: client (1 days, --path-walk)           0.02(0.02+0.00)   0.02(0.02+0.00) +0.0%
    5311.44: server (2 days, --path-walk)           1.43(1.39+0.04)   0.01(0.00+0.00) -99.3%
    5311.45: size   (2 days, --path-walk)                    139.6K            139.7K +0.0%
    5311.46: client (2 days, --path-walk)           0.02(0.02+0.00)   0.02(0.02+0.00) +0.0%
    5311.48: server (4 days, --path-walk)           1.44(1.39+0.04)   0.01(0.01+0.00) -99.3%
    5311.49: size   (4 days, --path-walk)                    238.1K            238.1K +0.0%
    5311.50: client (4 days, --path-walk)           0.03(0.03+0.00)   0.03(0.03+0.00) +0.0%
    5311.52: server (8 days, --path-walk)           1.43(1.39+0.03)   0.01(0.00+0.00) -99.3%
    5311.53: size   (8 days, --path-walk)                    344.9K            344.9K +0.0%
    5311.54: client (8 days, --path-walk)           0.07(0.07+0.00)   0.07(0.08+0.00) +0.0%
    5311.56: server (16 days, --path-walk)          1.47(1.44+0.03)   0.10(0.08+0.01) -93.2%
    5311.57: size   (16 days, --path-walk)                   844.0K            844.0K +0.0%
    5311.58: client (16 days, --path-walk)          0.09(0.09+0.00)   0.09(0.09+0.00) +0.0%
    5311.60: server (32 days, --path-walk)          1.52(1.50+0.05)   0.14(0.15+0.02) -90.8%
    5311.61: size   (32 days, --path-walk)                     4.2M              4.2M +0.1%
    5311.62: client (32 days, --path-walk)          0.34(0.48+0.02)   0.34(0.45+0.05) +0.0%
    5311.64: server (64 days, --path-walk)          1.55(1.52+0.06)   0.15(0.15+0.04) -90.3%
    5311.65: size   (64 days, --path-walk)                     6.4M              6.4M -0.0%
    5311.66: client (64 days, --path-walk)          0.51(0.79+0.05)   0.51(0.80+0.06) +0.0%
    5311.68: server (128 days, --path-walk)         1.59(1.57+0.06)   0.16(0.21+0.01) -89.9%
    5311.69: size   (128 days, --path-walk)                    8.4M              8.4M -0.0%
    5311.70: client (128 days, --path-walk)         0.72(1.44+0.08)   0.71(1.47+0.09) -1.4%

We get the same size of output pack, but this commit allows us to do so
in a significantly shorter amount of time. Intuitively, we're generating
the same pack (hence the unchanged 'test_size' output from run to run),
but varying how we get there. Before this commit, pack-objects prefers
'--path-walk' to '--use-bitmap-index', so we generate the output pack by
performing a normal '--path-walk' traversal. With this commit, we are
operating over a *repacked* state (that itself was done with a
'--path-walk' traversal), but are able to perform pack-reuse on that
repacked state via bitmaps.

When comparing the size of the repacked pack with/without '--path-walk'
on the previous commit versus this one, we see that (a) the repacked size
improves significantly with '--path-walk', and that (b) writing bitmaps
during repacking does not regress this improvement:

    Test                                            HEAD^             HEAD
    ----------------------------------------------------------------------------------------
    5311.3: size of bitmapped pack                           558.4M            558.5M +0.0%
    5311.38: size of bitmapped pack (--path-walk)            164.4M            164.4M +0.0%

(Note that to observe an improvement here, we must repack with '-F' in
order to avoid reusing non-'--path-walk' deltas, which would otherwise
skew our results.)

There is one wrinkle when it comes to '--boundary', which we must not
pass into the bitmap walk in the presence of both '--path-walk' and
'--use-bitmap-index'. Path-walk needs boundary commits when it performs
its own traversal, in order to discover bases for thin packs, but the
bitmap traversal does not expect this. Work around this by setting
`revs->boundary` as late as possible within the '--path-walk' traversal,
after any bitmap attempt has either succeeded or declined to answer the
request.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agot/perf: drop p5311's lookup-table permutation
Taylor Blau [Sun, 21 Jun 2026 23:02:59 +0000 (19:02 -0400)] 
t/perf: drop p5311's lookup-table permutation

p5311 measures the cost of serving a fetch from a bitmapped pack and
indexing the resulting pack on the client. Since 761416ef91d
(bitmap-lookup-table: add performance tests for lookup table,
2022-08-14), p5311 effectively runs itself twice: once with the bitmap's
lookup table extension enabled, and again with it disabled.

This comparison has served its useful purpose, as the lookup table is
almost four years old, and the de-facto default in server-side Git
deployments.

A following commit will want to test a different combination (repacking
with and without '--path-walk' instead of the lookup table). Instead of
multiplying the current test count by two again to produce four
variations of `test_fetch_bitmaps()`, drop the lookup table option to
reduce the number of perf tests we run. Retain `test_fetch_bitmaps()`
itself, since we will use this in the future for the new
parameterization.

(As an aside, a future commit outside of this series will adjust the
default value of 'pack.writeBitmapLookupTable' to "true", matching the
de-facto norm for deployments where the existence of bitmap lookup
tables is meaningful. Punt on that to a later series and instead make
the minimal change for now.)

Suggested-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agodoc: advise batching patch rerolls
Weijie Yuan [Sun, 21 Jun 2026 08:05:34 +0000 (16:05 +0800)] 
doc: advise batching patch rerolls

Contributors often need guidance on how quickly to send later iterations
of a patch series. Add a rough default of no more than one new version
of the same series per day so feedback can be batched and reviewers have
time to comment regardless of their time zones.

Mention factors that can affect the timing, such as series size, review
depth, and substantial rework. Also point out that avoiding rapid
rerolls encourages authors to polish each version before sending it, so
reviewers can focus on substantial issues.

Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Weijie Yuan <wy@wyuan.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agodoc: encourage review replies before rerolling
Weijie Yuan [Sun, 21 Jun 2026 08:05:06 +0000 (16:05 +0800)] 
doc: encourage review replies before rerolling

Review feedback should not be answered only by sending a new patch
version. Encourage contributors to discuss their planned response in the
mailing-list thread before rerolling.

This makes the author's reasoning explicit before the next version is
prepared, instead of forcing reviewers to infer it from the rerolled
patches. It also encourages more direct social interaction between
contributors and helps foster a more collaborative review process.

Signed-off-by: Weijie Yuan <wy@wyuan.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agogit-gui: reduce complexity of the quiet msgfmt rule
Johannes Sixt [Sun, 21 Jun 2026 09:55:14 +0000 (11:55 +0200)] 
git-gui: reduce complexity of the quiet msgfmt rule

In non-verbose builds (without V=1) the rule to compile *.po files with
msgfmt captures the output in a shell variable and then strips down the
text produced by --statistics to fit on a 80 column line. The previous
commit removed --statistics output of the msgfmt invocation, so that we
don't get to see anything beyond "MSGFMT po/xx.msg" anymore. Make the
rule as minimal as the other "quiet" rules.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
4 weeks agogit-gui: drop msgfmt --statistics output
Harald Nordgren [Sat, 20 Jun 2026 22:46:10 +0000 (22:46 +0000)] 
git-gui: drop msgfmt --statistics output

The catalog rules ran msgfmt with --statistics, whose output goes to
stderr and so survive "make -s".

The statistics are not needed, as in 2f12b31b746c (Makefile: don't
invoke msgfmt with --statistics, 2021-12-17). Remove it so a quiet
build stays quiet.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
[j6t: adjust commit message]
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
4 weeks agoSubmittingPatches: address design critiques
Junio C Hamano [Sat, 20 Jun 2026 23:43:00 +0000 (16:43 -0700)] 
SubmittingPatches: address design critiques

Contributors sometimes fail to answer fundamental design or
viability comments from reviewers and submit subsequent rounds
without addressing them.  When design decisions are resolved on the
mailing list, the final justification should be recorded in the
commit messages.

Instruct authors to be particularly mindful of critiques regarding
high-level design or viability, to defend their choices on the list,
and to accompany new iterations with clearer explanations in the cover
letter, responses, and revised commit messages. Also instruct them to
explicitly document the resolution of these concerns in the commit
message body to keep the historical record complete.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoenvironment: use 'repo->initialized' for repo_protect_hfs() and repo_protect_ntfs()
Tian Yuchen [Sat, 20 Jun 2026 14:09:57 +0000 (22:09 +0800)] 
environment: use 'repo->initialized' for repo_protect_hfs() and repo_protect_ntfs()

To match how we refrain from calling repo_config_values() on an
uninitialized instance of a repository object in other two topics
that deal with ignore_case and trust_executable_bit, check the
repo->initialized bit instead of the repo->gitdir member.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoconfig.mak.uname: avoid macOS dup-library warning
Harald Nordgren [Fri, 19 Jun 2026 20:32:07 +0000 (20:32 +0000)] 
config.mak.uname: avoid macOS dup-library warning

Building on macOS with Xcode 15 or newer emits:

    ld: warning: ignoring duplicate libraries: 'libgit.a',
    'target/release/libgitcore.a'

Some link recipes list the same archive twice, which is harmless.
Quiet the warning instead.

Pass -Wl,-no_warn_duplicate_libraries on Xcode 15 and newer, whose
linkers added both the warning and the suppression flag (ld64-907
and dyld-1009). Earlier linkers reject the flag, so gate on the
linker version. Broaden the existing -fno-common version probe to
also match the "ld64-NNN" and "dyld-NNN" forms Xcode 15 reports.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
4 weeks agoconfig: use repo_ignore_case() to access core.ignorecase
Tian Yuchen [Fri, 19 Jun 2026 15:51:52 +0000 (23:51 +0800)] 
config: use repo_ignore_case() to access core.ignorecase

Replace the accesses to the global 'ignore_case' variable with
calls to 'repo_ignore_case(the_repository)'. This step eliminates
the 'ignore_case' global state.

Note on compat/win32/path-utils.c:
To eliminate the global state, several helper functions
(e.g. 'win32_fspathncmp()') now read from
'repo_ignore_case(the_repository)'. While this introduces
dependency on 'repository.h' into the 'compat/', it avoids massive
refactoring of the signatures across the codebase.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com>
Mentored-by: Olamide Caleb Bello <belkid98@gmail.com>
Signed-off-by: Tian Yuchen <cat@malon.dev>
Signed-off-by: Junio C Hamano <gitster@pobox.com>