]> git.feebdaed.xyz Git - 0xmirror/git.git/log
0xmirror/git.git
5 weeks agoxdiff: use unambiguous types in xdl_hash_record()
Ezekiel Newren [Tue, 18 Nov 2025 22:34:17 +0000 (22:34 +0000)]
xdiff: use unambiguous types in xdl_hash_record()

Convert the function signature and body to use unambiguous types. char
is changed to uint8_t because this function processes bytes in memory.
unsigned long to uint64_t so that the hash output is consistent across
platforms. `flags` was changed from long to uint64_t to ensure the
high order bits are not dropped on platforms that treat long as 32
bits.

Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoxdiff: use size_t for xrecord_t.size
Ezekiel Newren [Tue, 18 Nov 2025 22:34:16 +0000 (22:34 +0000)]
xdiff: use size_t for xrecord_t.size

size_t is the appropriate type because size is describing the number of
elements, bytes in this case, in memory.

Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoxdiff: make xrecord_t.ptr a uint8_t instead of char
Ezekiel Newren [Tue, 18 Nov 2025 22:34:15 +0000 (22:34 +0000)]
xdiff: make xrecord_t.ptr a uint8_t instead of char

Make xrecord_t.ptr uint8_t because it's referring to bytes in memory.

In order to avoid a refactor avalanche, many uses of this field were
cast to char* or similar.

Places where casting was unnecessary:
xemit.c:156
xmerge.c:124
xmerge.c:127
xmerge.c:164
xmerge.c:169
xmerge.c:172
xmerge.c:178

Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoxdiff: use ptrdiff_t for dstart/dend
Ezekiel Newren [Tue, 18 Nov 2025 22:34:14 +0000 (22:34 +0000)]
xdiff: use ptrdiff_t for dstart/dend

ptrdiff_t is appropriate for dstart and dend because they both describe
positive or negative offsets relative to a pointer.

Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agodoc: define unambiguous type mappings across C and Rust
Ezekiel Newren [Tue, 18 Nov 2025 22:34:13 +0000 (22:34 +0000)]
doc: define unambiguous type mappings across C and Rust

Document other nuances when crossing the FFI boundary. Other language
mappings may be added in the future.

Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agorepo: add --all to git-repo-info
Lucas Seiki Oshiro [Tue, 18 Nov 2025 20:37:04 +0000 (17:37 -0300)]
repo: add --all to git-repo-info

Add a new flag `--all` to git-repo-info for requesting values for all
the available keys. By using this flag, the user can retrieve all the
values instead of searching what are the desired keys for what they
wants.

Helped-by: Karthik Nayak <karthik.188@gmail.com>
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agorepo: factor out field printing to dedicated function
Lucas Seiki Oshiro [Tue, 18 Nov 2025 20:37:03 +0000 (17:37 -0300)]
repo: factor out field printing to dedicated function

Move the field printing in git-repo-info to a new function called
`print_field`, allowing it to be called by functions other than
`print_fields`.

Also change its use of quote_c_style() helper to output directly to
the standard output stream, instead of taking a result in a strbuf
and then printing it outselves.

Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoworktree list: quote paths
Phillip Wood [Tue, 18 Nov 2025 16:07:33 +0000 (16:07 +0000)]
worktree list: quote paths

If a worktree path contains newlines or other control characters
it messes up the output of "git worktree list". Fix this by using
quote_path() to display the worktree path. The output of "git worktree
list" is designed for human consumption, scripts should be using the
"--porcelain" option so this change should not break them.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoworktree list: fix column spacing
Phillip Wood [Tue, 18 Nov 2025 16:07:32 +0000 (16:07 +0000)]
worktree list: fix column spacing

The output of "git worktree list" displays a table containing the
worktree path, HEAD OID and branch name for each worktree. The code
aligns the columns by measuring the visual width of the worktree path
when it is printed. Unfortunately it fails to use the visual width
when calculating the width of the column so, if any of the paths
contain a multibyte character, we can end up with excess padding
between columns. The simplest fix would be to replace strlen() with
utf8_strwidth() in measure_widths(). However that leaves us measuring
the visual width twice and the byte length once. By caching the visual
width and printing the padding separately to the worktree path, we only
need to calculate the visual width once and do not need the byte length
at all. The visual widths are stored in an arrays of structs rather
than an array of ints as the next commit will add more struct members.

Even if there are no multibyte characters in any of the paths we still
print an extra space between the path and the object id as the field
width is calculated as one plus the length of the path and we print an
explicit space as well. This is fixed by not printing the extra space.

The tests are updated to include multibyte characters in one of the
worktree paths and to check the spacing of the columns.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agotest-mktemp: plug memory and descriptor leaks
Jeff King [Tue, 18 Nov 2025 12:21:24 +0000 (07:21 -0500)]
test-mktemp: plug memory and descriptor leaks

We test xmkstemp() in our helper by just calling:

  xmkstemp(xstrdup(argv[1]));

This leaks both the copied string as well as the descriptor returned by
the function. In practice this isn't a big deal, since we immediately
exit the program, but:

  1. LSan will complain about the memory leak. The only reason we did
     not notice this in our leak-checking builds is that both of the
     callers in the test suite (both in t0070) pass a broken template
     (and expect failure). So the function calls die() before we can
     actually leak.

     But it's an accident waiting to happen if anybody adds a call which
     succeeds.

  2. Coverity complains about the descriptor leak. There's a long list
     of uninteresting or false positives in Coverity's results, but
     since we're here we might as well fix it, too.

I didn't bother adding a new test that triggers the leak. It's not even
in real production code, but just in the test-helper itself.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoci(windows-meson-test): handle options and output like other test jobs
Jeff King [Tue, 18 Nov 2025 09:35:19 +0000 (04:35 -0500)]
ci(windows-meson-test): handle options and output like other test jobs

The GitHub windows-meson-test jobs directly run "meson test" with the
--slice option. This means they skip all of the ci/lib.sh
infrastructure, and in particular:

  1. They do not actually set any GIT_TEST_OPTS like --verbose-log or
     -x.

  2. They do not do the usual handle_failed_tests() magic to print test
     failures or tar up failed directories.

As a result, you get almost no feedback at all when a test fails in this
job, making debugging rather tricky.

Let's try to make this behave more like the other CI jobs. Because we're
on Windows, we can't just use the normal run-build-and-tests.sh script.
Our build runs as a separate job (like the non-meson Windows job), and
then we parallelize the tests across several job slices. So we need
something like the run-test-slice.sh script that the "windows-test" job
uses.

In theory we could just swap out the "make" invocation there for
"meson". But it doesn't quite work, because "make" knows how to pull
GIT_TEST_OPTS out of GIT-BUILD-OPTIONS automatically. But for meson, we
have to extract them into the --test-args option ourselves. I tried
making the logic in run-test-slice.sh conditional, but there ended up
being hardly any common code at all (and there are some tricky ordering
constraints). So I added up with a new meson-specific test-slice runner.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agounit-test: ignore --no-chain-lint
Jeff King [Tue, 18 Nov 2025 09:32:43 +0000 (04:32 -0500)]
unit-test: ignore --no-chain-lint

In the same spirit as 9faf3963b6 (t: introduce compatibility options to
clar-based tests, 2024-12-13), we should ignore --no-chain-lint passed
to our clar tests, since it may appear in GIT_TEST_OPTS to be used with
other tests.

This is particularly important on Windows CI, where --no-chain-lint is
added to the test options by default, and the meson build will pass all
options to the unit tests. The only reason our meson Windows CI job does
not run into this currently is that it is not respecting GIT_TEST_OPTS
at all! So ignoring this option is a prerequisite to fixing that
situation.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agot: enable ASan's strict_string_checks option
Jeff King [Tue, 18 Nov 2025 09:12:30 +0000 (04:12 -0500)]
t: enable ASan's strict_string_checks option

ASan has an option to enable strict string checking, where any pointer
passed to a function that expects a NUL-terminated string will be
checked for that NUL termination. This can sometimes produce false
positives. E.g., it is not wrong to pass a buffer with { '1', '2', '\n' }
into strtoul(). Even though it is not NUL-terminated, it will stop at
the newline.

But in trying it out, it identified two problematic spots in our test
suite (which have now been adjusted):

  1. The strtol() parsing in cache-tree.c was a real potential problem,
     which would have been very hard to find otherwise (since it
     required constructing a very specific broken index file).

  2. The use of string functions in fsck_ident() were false positives,
     because we knew that there was always a trailing newline which
     would stop the functions from reading off the end of the buffer.
     But the reasoning behind that is somewhat fragile, and silencing
     those complaints made the code easier to reason about.

So even though this did not find any earth-shattering bugs, and even had
a few false positives, I'm sufficiently convinced that its complaints
are more helpful than hurtful. Let's turn it on by default (since the
test suite now runs cleanly with it) and see if it ever turns up any
other instances.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agofsck: avoid parse_timestamp() on buffer that isn't NUL-terminated
Jeff King [Tue, 18 Nov 2025 09:12:28 +0000 (04:12 -0500)]
fsck: avoid parse_timestamp() on buffer that isn't NUL-terminated

In fsck_ident(), we parse the timestamp with parse_timestamp(), which is
really an alias for strtoumax(). But since our buffer may not be
NUL-terminated, this can trigger a complaint from ASan's
strict_string_checks mode. This is a false positive, since we know that
the buffer contains a trailing newline (which we checked earlier in the
function), and that strtoumax() would stop there.

But it is worth working around ASan's complaint. One is because that
will let us turn on strict_string_checks by default, which has helped
catch other real problems. And two is that the safety of the current
code is very hard to reason about (it subtly depends on distant code
which could change).

One option here is to just parse the number left-to-right ourselves. But
we care about the size of a timestamp_t and detecting overflow, since
that's part of the point of these checks. And doing that correctly is
tricky. So we'll instead just pull the digits into a separate,
NUL-terminated buffer, and use that to call parse_timestamp().

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agofsck: remove redundant date timestamp check
Jeff King [Tue, 18 Nov 2025 09:12:25 +0000 (04:12 -0500)]
fsck: remove redundant date timestamp check

After calling "parse_timestamp(p, &end, 10)", we complain if "p == end",
which would imply that we did not see any digits at all. But we know
this cannot be the case, since we would have bailed already if we did
not see any digits, courtesy of extra checks added by 8e4309038f (fsck:
do not assume NUL-termination of buffers, 2023-01-19). Since then,
checking "p == end" is redundant and we can drop it.

This will make our lives a little easier as we refactor further.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agofsck: avoid strcspn() in fsck_ident()
Jeff King [Tue, 18 Nov 2025 09:12:23 +0000 (04:12 -0500)]
fsck: avoid strcspn() in fsck_ident()

We may be operating on a buffer that is not NUL-terminated, but we use
strcspn() to parse it. This is OK in practice, as discussed in
8e4309038f (fsck: do not assume NUL-termination of buffers, 2023-01-19),
because we know there is at least a trailing newline in our buffer, and
we always pass "\n" to strcspn(). So we know it will stop before running
off the end of the buffer.

But this is a subtle point to hang our memory safety hat on. And it
confuses ASan's strict_string_checks mode, even though it is technically
a false positive (that mode complains that we have no NUL, which is
true, but it does not know that we have verified the presence of the
newline already).

Let's instead open-code the loop. As a bonus, this makes the logic more
obvious (to my mind, anyway). The current code skips forward with
strcspn until it hits "<", ">", or "\n". But then it must check which it
saw to decide if that was what we expected or not, duplicating some
logic between what's in the strcspn() and what's in the domain logic.
Instead, we can just check each character as we loop and act on it
immediately.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agofsck: assert newline presence in fsck_ident()
Jeff King [Tue, 18 Nov 2025 09:12:20 +0000 (04:12 -0500)]
fsck: assert newline presence in fsck_ident()

The fsck code purports to handle buffers that are not NUL-terminated,
but fsck_ident() uses some string functions. This works OK in practice,
as explained in 8e4309038f (fsck: do not assume NUL-termination of
buffers, 2023-01-19). Before calling fsck_ident() we'll have called
verify_headers(), which makes sure we have at least a trailing newline.
And none of our string-like functions will walk past that newline.

However, that makes this code at the top of fsck_ident() very confusing:

    *ident = strchrnul(*ident, '\n');
    if (**ident == '\n')
            (*ident)++;

We should always see that newline, or our memory safety assumptions have
been violated! Further, using strchrnul() is weird, since the whole
point is that if the newline is not there, we don't necessarily have a
NUL at all, and might read off the end of the buffer.

So let's have callers pass in the boundary of our buffer, which lets us
safely find the newline with memchr(). And if it is not there, this is a
BUG(), because it means our caller did not validate the input with
verify_headers() as it was supposed to (and we are better off bailing
rather than having memory-safety problems).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agocache-tree: avoid strtol() on non-string buffer
Jeff King [Tue, 18 Nov 2025 09:12:18 +0000 (04:12 -0500)]
cache-tree: avoid strtol() on non-string buffer

A cache-tree extension entry in the index looks like this:

  <name> NUL <entry_nr> SPACE <subtree_nr> NEWLINE <binary_oid>

where the "_nr" items are human-readable base-10 ASCII. We parse them
with strtol(), even though we do not have a NUL-terminated string (we'd
generally have an mmap() of the on-disk index file). For a well-formed
entry, this is not a problem; strtol() will stop when it sees the
newline. But there are two problems:

  1. A corrupted entry could omit the newline, causing us to read
     further. You'd mostly get stopped by seeing non-digits in the oid
     field (and if it is likewise truncated, there will still be 20 or
     more bytes of the index checksum). So it's possible, though
     unlikely, to read off the end of the mmap'd buffer. Of course a
     malicious index file can fake the oid and the index checksum to all
     (ASCII) 0's.

     This is further complicated by the fact that mmap'd buffers tend to
     be zero-padded up to the page boundary. So to run off the end, the
     index size also has to be a multiple of the page size. This is also
     unlikely, though you can construct a malicious index file that
     matches this.

     The security implications aren't too interesting. The index file is
     a local file anyway (so you can't attack somebody by cloning, but
     only if you convince them to operate in a .git directory you made,
     at which point attacking .git/config is much easier). And it's just
     a read overflow via strtol(), which is unlikely to buy you much
     beyond a crash.

  2. ASan has a strict_string_checks option, which tells it to make sure
     that options to string functions (like strtol) have some eventual
     NUL, without regard to what the function would actually do (like
     stopping at a newline here). This option sometimes has false
     positives, but it can point to sketchy areas (like this one) where
     the input we use doesn't exhibit a problem, but different input
     _could_ cause us to misbehave.

Let's fix it by just parsing the values ourselves with a helper function
that is careful not to go past the end of the buffer. There are a few
behavior changes here that should not matter:

  - We do not consider overflow, as strtol() would. But nor did the
    original code. However, we don't trust the value we get from the
    on-disk file, and if it says to read 2^30 entries, we would notice
    that we do not have that many and bail before reading off the end of
    the buffer.

  - Our helper does not skip past extra leading whitespace as strtol()
    would, but according to gitformat-index(5) there should not be any.

  - The original quit parsing at a newline or a NUL byte, but now we
    insist on a newline (which is what the documentation says, and what
    Git has always produced).

Since we are providing our own helper function, we can tweak the
interface a bit to make our lives easier. The original code does not use
strtol's "end" pointer to find the end of the parsed data, but rather
uses a separate loop to advance our "buf" pointer to the trailing
newline. We can instead provide a helper that advances "buf" as it
parses, letting us read strictly left-to-right through the buffer.

I didn't add a new test here. It's surprisingly difficult to construct
an index of exactly the right size due to the way we pad entries. But it
is easy to trigger the problem in existing tests when using ASan's
strict string checking, coupled with a recent change to use NO_MMAP with
ASan builds. So:

  make SANITIZE=address
  cd t
  ASAN_OPTIONS=strict_string_checks=1 ./t0090-cache-tree.sh

triggers it reliably. Technically it is not deterministic because there
is ~8% chance (it's 1-(255/256)^20, or ^32 for sha256) that the trailing
checksum hash has a NUL byte in it. But we compute enough cache-trees in
the course of that script that we are very likely to hit the problem in
one of them.

We can look at making strict_string_checks the default for ASan builds,
but there are some other cases we'd want to fix first.

Reported-by: correctmost <cmlists@sent.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoMakefile: turn on NO_MMAP when building with ASan
Jeff King [Tue, 18 Nov 2025 09:12:13 +0000 (04:12 -0500)]
Makefile: turn on NO_MMAP when building with ASan

Git often uses mmap() to access on-disk files. This leaves a blind spot
in our SANITIZE=address builds, since ASan does not seem to handle mmap
at all. Nor does the OS notice most out-of-bounds access, since it tends
to round up to the nearest page size (so depending on how big the map
is, you might have to overrun it by up to 4095 bytes to trigger a
segfault).

The previous commit demonstrates a memory bug that we missed. We could
have made a new test where the out-of-bounds access was much larger, or
where the mapped file ended closer to a page boundary. But the point of
running the test suite with sanitizers is to catch these problems
without having to construct specific tests.

Let's enable NO_MMAP for our ASan builds by default, which should give
us better coverage. This does increase the memory usage of Git, since
we're copying from the filesystem into heap. But the repositories in the
test suite tend to be small, so the overhead isn't really noticeable
(and ASan already has quite a performance penalty).

There are a few other known bugs that this patch will help flush out.
However, they aren't directly triggered in the test suite (yet). So
it's safe to turn this on now without breaking the test suite, which
will help us add new tests to demonstrate those other bugs as we fix
them.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agopack-bitmap: handle name-hash lookups in incremental bitmaps
Jeff King [Tue, 18 Nov 2025 09:12:06 +0000 (04:12 -0500)]
pack-bitmap: handle name-hash lookups in incremental bitmaps

If a bitmap has a name-hash cache, it is an array of 32-bit integers,
one per entry in the bitmap, which we've mmap'd from the .bitmap file.
We access it directly like this:

    if (bitmap_git->hashes)
            hash = get_be32(bitmap_git->hashes + index_pos);

That works for both regular pack bitmaps and for non-incremental midx
bitmaps. There is one bitmap_index with one "hashes" array, and
index_pos is within its bounds (we do the bounds-checking when we load
the bitmap).

But for an incremental midx bitmap, we have a linked list of
bitmap_index structs, and each one has only its own small slice of the
name-hash array. If index_pos refers to an object that is not in the
first bitmap_git of the chain, then we'll access memory outside of the
bounds of its "hashes" array, and often outside of the mmap.

Instead, we should walk through the list until we find the bitmap_index
which serves our index_pos, and use its hash (after adjusting index_pos
to make it relative to the slice we found). This is exactly what we do
elsewhere for incremental midx lookups (like the pack_pos_to_midx() call
a few lines above). But we can't use existing helpers like
midx_for_object() here, because we're walking through the chain of
bitmap_index structs (each of which refers to a midx), not the chain of
incremental multi_pack_index structs themselves.

The problem is triggered in the test suite, but we don't get a segfault
because the out-of-bounds index is too small. The OS typically rounds
our mmap up to the nearest page size, so we just end up accessing some
extra zero'd memory. Nor do we catch it with ASan, since it doesn't seem
to instrument mmaps at all. But if we build with NO_MMAP, then our maps
are replaced with heap allocations, which ASan does check. And so:

  make NO_MMAP=1 SANITIZE=address
  cd t
  ./t5334-incremental-multi-pack-index.sh

does show the problem (and this patch makes it go away).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agocompat/mmap: mark unused argument in git_munmap()
Jeff King [Tue, 18 Nov 2025 09:11:56 +0000 (04:11 -0500)]
compat/mmap: mark unused argument in git_munmap()

Our mmap compat code emulates mapping by using malloc/free. Our
git_munmap() must take a "length" parameter to match the interface of
munmap(), but we don't use it (it is up to the allocator to know how big
the block is in free()).

Let's mark it as UNUSED to avoid complaints from -Wunused-parameter.
Otherwise you cannot build with "make DEVELOPER=1 NO_MMAP=1".

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoci: bump actions/setup-go from 5 to 6
Johannes Schindelin [Tue, 18 Nov 2025 07:26:45 +0000 (02:26 -0500)]
ci: bump actions/setup-go from 5 to 6

Bumps actions/setup-go from 5 to 6. This upgrade includes dependency
updates that incorporate a fix for a critical vulnerability.
[Originally opened at https://github.com/git-for-windows/git/pull/5811]

- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

Originally-authored-by: dependabot[bot] <support@github.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agomingw: avoid the comma operator
Johannes Schindelin [Mon, 17 Nov 2025 20:46:14 +0000 (20:46 +0000)]
mingw: avoid the comma operator

The pattern `return errno = ..., -1;` is observed several times in
`compat/mingw.c`. It has served us well over the years, but now clang
starts complaining:

  compat/mingw.c:723:24: error: possible misuse of comma operator here [-Werror,-Wcomma]
    723 |                 return errno = ENOSYS, -1;
        |                                      ^

See for example this failing workflow run:
https://github.com/git-for-windows/git-sdk-arm64/actions/runs/15457893907/job/43513458823#step:8:201

Let's appease clang (and also reduce the use of the no longer common
comma operator).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agocmake: stop trying to build the reftable and xdiff libraries
Johannes Schindelin [Mon, 17 Nov 2025 20:40:08 +0000 (20:40 +0000)]
cmake: stop trying to build the reftable and xdiff libraries

In the `en/make-libgit-a` topic branch, more precisely in the commits
f3b4c89d59f1 (make: delete REFTABLE_LIB, add reftable to LIB_OBJS,
2025-10-02) and cf680cdb9543 (make: delete XDIFF_LIB, add xdiff to
LIB_OBJS, 2025-10-02), the strategy to build three static libraries was
rethought, and instead only one static library is now built.

This is good.

However, the CMake definition was not changed accordingly, and now
CMake-based builds fail thusly:

  [...]
  Generating hook-list.h
  CMake Error at CMakeLists.txt:122 (string):
    string sub-command REPLACE requires at least four arguments.
  Call Stack (most recent call first):
    CMakeLists.txt:711 (parse_makefile_for_sources)

  CMake Error at CMakeLists.txt:122 (string):
    string sub-command REPLACE requires at least four arguments.
  Call Stack (most recent call first):
    CMakeLists.txt:717 (parse_makefile_for_sources)

  -- Configuring incomplete, errors occurred!

Fix that by removing the parts that expect the reftable and xdiff
objects to be defined separately in the Makefile, still.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agowincred: avoid memory corruption
David Macek [Mon, 17 Nov 2025 20:39:44 +0000 (20:39 +0000)]
wincred: avoid memory corruption

`wcsncpy_s()` wants to write the terminating null character so we need
to allocate one more space for it in the target memory block.

This should fix crashes when trying to read passwords.  When this
happened, the password/token wouldn't print out and Git would therefore
ask for a new password every time.

Signed-off-by: David Macek <david.macek.0@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agomerge-ort: fix failing merges in special corner case
Elijah Newren [Mon, 3 Nov 2025 18:01:48 +0000 (18:01 +0000)]
merge-ort: fix failing merges in special corner case

At GitHub, we had a repository that was triggering
  git: merge-ort.c:3032: process_renames: Assertion `newinfo && !newinfo->merged.clean` failed.
during git replay.

This sounds similar to the somewhat recent f6ecb603ff8a (merge-ort: fix
directory rename on top of source of other rename/delete, 2025-08-06),
but the cause is different.  Unlike that case, there are no
rename-to-self situations arising in this case, and new to this case it
can only be triggered during a replay operation on the 2nd or later
commit being replayed, never on the first merge in the sequence.

To trigger, the repository needs:
  * an upstream which:
    * renames a file to a different directory, e.g.
        old/file -> new/file
    * leaves other files remaining in the original directory (so that
      e.g. "old/" still exists upstream even though file has been
      removed from it and placed elsewhere)
  * a topic branch being rebased where:
    * a commit in the sequence:
      * modifies old/file
    * a subsequent commit in the sequence being replayed:
      * does NOT touch *anything* under new/
      * does NOT touch old/file
      * DOES modify other paths under old/
      * does NOT have any relevant renames that we need to detect
        _anywhere_ elsewhere in the tree (meaning this interacts
        interestingly with both directory renames and cached renames)

In such a case, the assertion will trigger.  The fix turns out to be
surprisingly simple.  I have a very vague recollection that I actually
considered whether to add such an if-check years ago when I added the
very similar one for oldinfo in 1b6b902d95a5 (merge-ort:
process_renames() now needs more defensiveness, 2021-01-19), but I think
I couldn't figure out a possible way to trigger it and was worried at
the time that if I didn't know how to trigger it then I wasn't so sure
that simply skipping it was correct.  Waiting did give me a chance to
put more thorough tests and checks into place for the rename-to-self
cases a few months back, which I might not have found as easily
otherwise.  Anyway, put the check in place now and add a test that
demonstrates the fix.

Note that this bug, as demonstrated by the conditions listed above,
runs at the intersection of relevant renames, trivial directory
resolutions, and cached renames.  All three of those optimizations are
ones that unfortunately make the code (and testcases!) a bit more
complex, and threading all three makes it a bit more so.  However, the
testcase isn't crazy enough that I'd expect no one to ever hit it in
practice, and was confused why we didn't see it before.  After some
digging, I discovered that merge.directoryRenames=false is a workaround
to this bug, and GitHub used that setting until recently (it was a
"temporary" match-what-libgit2-does piece of code that lasted years
longer than intended).  Since the conditions I gave above for triggering
this bug rule out the possibility of there being directory renames, one
might assume that it shouldn't matter whether you try to detect such
renames if there aren't any.  However, due to commit a16e8efe5c2b
(merge-ort: fix merge.directoryRenames=false, 2025-03-13), the heavy
hammer used there means that merge.directoryRenames=false ALSO turns off
rename caching, which is critical to triggering the bug.  This becomes
a bit more than an aside since...

Re-reading that old commit, a16e8efe5c2b (merge-ort: fix
merge.directoryRenames=false, 2025-03-13), it appears that the solution
to this latest bug might have been at least a partial alternative
solution to that old commit.  And it may have been an improved
alternative (or at least help implement one), since it may be able to
avoid the heavy-handed disabling of rename cache.  That might be an
interesting future thing to investigate, but is not critical for the
current fix.  However, since I spent time digging it all up, at least
leave a small comment tweak breadcrumb to help some future reader
(myself or others) who wants to dig further to connect the dots a little
quicker.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agomerge-ort: remove debugging crud
Elijah Newren [Mon, 3 Nov 2025 18:01:47 +0000 (18:01 +0000)]
merge-ort: remove debugging crud

While developing commit a16e8efe5c2b (merge-ort: fix
merge.directoryRenames=false, 2025-03-13), I was testing things out and
had an extra condition on one of the if-blocks that I occasionally
swapped between '&& 0' and '&& 1' to see the effects of the changes.  I
forgot to remove it before submitting and it wasn't caught in review.
Remove it now.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agot6429: update comment to mention correct tool
Elijah Newren [Mon, 3 Nov 2025 18:01:46 +0000 (18:01 +0000)]
t6429: update comment to mention correct tool

A comment at the top of t6429 mentions why the test doesn't exercise git
rebase or git cherry-pick.  However, it claims that it uses `test-tool
fast-rebase`.  That was true when the comment was written, but commit
f920b0289ba3 (replay: introduce new builtin, 2023-11-24) changed it to
use git replay without updating this comment.

We could potentially just strike this second comment, since git replay
is a bona fide built-in, but perhaps the explanation about why it focuses
on git replay is still useful.  Update the comment to make it accurate
again.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agomake strip: include `scalar`
Johannes Schindelin [Mon, 17 Nov 2025 19:51:26 +0000 (19:51 +0000)]
make strip: include `scalar`

When Scalar was made a canonical part of Git in 7b5c93c6c68 (scalar:
include in standard Git build & installation, 2022-09-02), it was added
to all relevant Makefile targets except for the `strip` target.

Let's correct that.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agowrapper: simplify xmkstemp()
René Scharfe [Mon, 17 Nov 2025 19:42:55 +0000 (20:42 +0100)]
wrapper: simplify xmkstemp()

Call xmkstemp_mode() instead of duplicating its error handling code.
This switches the implementation from the system's mkstemp(3) to our own
git_mkstemp_mode(), which works just as well.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoblame: make diff algorithm configurable
Antonin Delpeuch [Mon, 17 Nov 2025 08:04:32 +0000 (08:04 +0000)]
blame: make diff algorithm configurable

The diff algorithm used in 'git-blame(1)' is set to 'myers',
without the possibility to change it aside from the `--minimal` option.

There has been long-standing interest in changing the default diff
algorithm to "histogram", and Git 3.0 was floated as a possible occasion
for taking some steps towards that:

https://lore.kernel.org/git/xmqqed873vgn.fsf@gitster.g/

As a preparation for this move, it is worth making sure that the diff
algorithm is configurable where useful.

Make it configurable in the `git-blame(1)` command by introducing the
`--diff-algorithm` option and make honor the `diff.algorithm` config
variable. Keep Myers diff as the default.

Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoxdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK
Antonin Delpeuch [Mon, 17 Nov 2025 08:04:31 +0000 (08:04 +0000)]
xdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK

The XDF_DIFF_ALGORITHM_MASK bit mask only includes bits for the patience
and histogram diffs, not for the minimal one. This means that when
reseting the diff algorithm to the default one, one needs to separately
clear the bit for the minimal diff. There are places in the code that fail
to do that: merge-ort.c and builtin/merge-file.c.

Add the XDF_NEED_MINIMAL bit to the bit mask, and remove the separate
clearing of this bit in the places where it hasn't been forgotten.

Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agoGit 2.52
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>
5 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

5 weeks agocommit: refactor verify_commit_buffer()
Christian Couder [Mon, 17 Nov 2025 04:34:49 +0000 (05:34 +0100)]
commit: refactor verify_commit_buffer()

In a following commit, we are going to check commit signatures, but we
won't have a commit yet, only a commit buffer, and we are going to
discard this commit buffer if the signature is invalid. So it would be
wasteful to create a commit that we might discard, just to be able to
check a commit signature.

It would be simpler instead to be able to check commit signatures
using only a commit buffer instead of a commit.

To be able to do that, let's extract some code from the
check_commit_signature() function into a new verify_commit_buffer()
function, and then let's make check_commit_signature() call
verify_commit_buffer().

Note that this doesn't fundamentally change how
check_commit_signature() works. It used to call parse_signed_commit()
which calls repo_get_commit_buffer(), parse_buffer_signed_by_header()
and repo_unuse_commit_buffer(). Now these 3 functions are called
directly by verify_commit_buffer().

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agofast-import: refactor finalize_commit_buffer()
Christian Couder [Mon, 17 Nov 2025 04:34:48 +0000 (05:34 +0100)]
fast-import: refactor finalize_commit_buffer()

In a following commit we are going to finalize commit buffers with or
without signatures in order to check the signatures and possibly drop
them.

To do so easily and without duplication, let's refactor the current
code that finalizes commit buffers into a new finalize_commit_buffer()
function.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agobuiltin/repo: fix table alignment for UTF-8 characters
Jiang Xin [Sat, 15 Nov 2025 13:36:11 +0000 (08:36 -0500)]
builtin/repo: fix table alignment for UTF-8 characters

The output table from "git repo structure" is misaligned when displaying
UTF-8 characters (e.g., non-ASCII glyphs). E.g.:

    | 仓库结构   | 值  |
    | -------------- | ---- |
    | * 引用       |      |
    |   * 计数     |   67 |

The previous implementation used simple width formatting with printf()
which didn't properly handle multi-byte UTF-8 characters, causing
misaligned table columns when displaying repository structure
information.

This change modifies the stats_table_print_structure function to use
strbuf_utf8_align() instead of basic printf width specifiers. This
ensures proper column alignment regardless of the character encoding of
the content being displayed.

Also add test cases for strbuf_utf8_align(), a function newly introduced
in "builtin/repo.c".

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 weeks agot/unit-tests: add UTF-8 width tests for CJK chars
Jiang Xin [Sat, 15 Nov 2025 13:36:10 +0000 (08:36 -0500)]
t/unit-tests: add UTF-8 width tests for CJK chars

The file "builtin/repo.c" uses utf8_strwidth() to calculate the display
width of UTF-8 characters in a table, but the resulting output is still
misaligned. Add test cases for both utf8_strwidth and utf8_strnwidth to
verify that they correctly compute the display width for UTF-8
characters.

Also updated the build configuration in Makefile and meson.build to
include the new test suite in the build process.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 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>
5 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

5 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>
5 weeks agoread-cache: drop submodule check from add_to_cache()
Jeff King [Sat, 15 Nov 2025 00:58:18 +0000 (00:58 +0000)]
read-cache: drop submodule check from add_to_cache()

In add_to_cache(), we treat any directories as submodules, and complain
if we can't resolve their HEAD. This call to resolve_gitlink_ref() was
added by f937bc2f86 (add: error appropriately on repository with no
commits, 2019-04-09), with the goal of improving the error message for
empty repositories.

But we already resolve the submodule HEAD in index_path(), which is
where we find the actual oid we're going to use. Resolving it again here
introduces some downsides:

  1. It's more work, since we have to open up the submodule repository's
     files twice.

  2. There are call paths that get to index_path() without going through
     add_to_cache(). For instance, we'd want a similar informative
     message if "git diff empty" finds that it can't resolve the
     submodule's HEAD. (In theory we can also get there through
     update-index, but AFAICT it refuses to consider directories as
     submodules at all, and just complains about them).

  3. The resolution in index_path() catches more errors that we don't
     handle here. In particular, it will validate that the object format
     for the submodule matches that of the superproject. This isn't a
     bug, since our call in add_to_cache() throws away the oid it gets
     without looking at it. But it certainly caused confusion for me
     when looking at where the object-format check should go.

So instead of resolving the submodule HEAD in add_to_cache(), let's just
teach the call in index_path() to actually produce an error message
(which it already does for other cases). That's probably what f937bc2f86
should have done in the first place, and it gives us a single point of
resolution when adding a submodule to the index.

The resulting output is slightly more verbose, as we propagate the error
up the call stack, but I think that's OK (and again, matches many other
errors we get when indexing fails).

I've left the text of the error message as-is, though it is perhaps
overly specific.  There are many reasons that resolving the submodule
HEAD might fail, though outside of corruption or system errors it is
probably most likely that the submodule HEAD is simply on an unborn
branch.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 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

6 weeks agoobject-file: disallow adding submodules of different hash algo
brian m. carlson [Sat, 15 Nov 2025 00:58:17 +0000 (00:58 +0000)]
object-file: disallow adding submodules of different hash algo

The design of the hash algorithm transition plan is that objects stored
must be entirely in one algorithm since we lack any way to indicate a
mix of algorithms.  This also includes submodules, but we have
traditionally not enforced this, which leads to various problems when
trying to clone or check out the the submodule from the remote.

Since this cannot work in the general case, restrict adding a submodule
of a different algorithm to the index.  Add tests for git add and git
submodule add that these are rejected.

Note that we cannot check this in git fsck because the malformed
submodule is stored in the tree as an object ID which is either
truncated (when a SHA-256 submodule is added to a SHA-1 repository) or
padded with zeros (when a SHA-1 submodule is added to a SHA-256
repository).  We cannot detect even the latter case because someone
could have an actual submodule that actually ends in 24 zeros, which
would be a false positive.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 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>
6 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

6 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

6 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

6 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)

6 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

6 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

6 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

6 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>
6 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>
6 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>
6 weeks agodoc: commit: link to git-status(1) on all format options
Kristoffer Haugsbakk [Fri, 14 Nov 2025 14:04:47 +0000 (15:04 +0100)]
doc: commit: link to git-status(1) on all format options

`--branch` and `--long` refer to git-status(1) options but they don’t tell us
what `short-format` and `long-format` are, respectively. And `--null`
mentions “status” but does not link to the command.

Refer to git-config(1) on `--branch` like `--short` does.

`long-format` is the git-status(1) output. So we can just say that
directly.

Replace “status” with a `linkgit` on `--null`.

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoosxkeychain: avoid incorrectly skipping store operation
Koji Nakamaru [Fri, 14 Nov 2025 06:04:30 +0000 (06:04 +0000)]
osxkeychain: avoid incorrectly skipping store operation

git-credential-osxkeychain skips storing a credential if its "get"
action sets "state[]=osxkeychain:seen=1". This behavior was introduced
in e1ab45b2 (osxkeychain: state to skip unnecessary store operations,
2024-05-15), which appeared in v2.46.

However, this state[] persists even if a credential returned by
"git-credential-osxkeychain get" is invalid and a subsequent helper's
"get" operation returns a valid credential. Another subsequent helper
(such as [1]) may expect git-credential-osxkeychain to store the valid
credential, but the "store" operation is incorrectly skipped because it
only checks "state[]=osxkeychain:seen=1".

To solve this issue, "state[]=osxkeychain:seen" needs to contain enough
information to identify whether the current "store" input matches the
output from the previous "get" operation (and not a credential from
another helper).

Set "state[]=osxkeychain:seen" to a value encoding the credential output
by "get", and compare it with a value encoding the credential input by
"store".

[1]: https://github.com/hickford/git-credential-oauth

Reported-by: Petter Sælen <petter@saelen.eu>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Koji Nakamaru <koji.nakamaru@gree.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoattr: enable incomplete-line whitespace error for this project
Junio C Hamano [Wed, 12 Nov 2025 22:02:58 +0000 (14:02 -0800)]
attr: enable incomplete-line whitespace error for this project

Now "git diff --check" and "git apply --whitespace=warn/fix" learned
incomplete line is a whitespace error, enable them for this project
to prevent patches to add new incomplete lines to our source to both
code and documentation files.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 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>
6 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>
6 weeks agodiff: highlight and error out on incomplete lines
Junio C Hamano [Wed, 12 Nov 2025 22:02:57 +0000 (14:02 -0800)]
diff: highlight and error out on incomplete lines

Teach "git diff" to highlight "\ No newline at end of file" message
as a whitespace error when incomplete-line whitespace error class is
in effect.  Thanks to the previous refactoring of complete rewrite
code path, we can do this at a single place.

Unlike whitespace errors in the payload where we need to annotate in
line, possibly using colors, the line that has whitespace problems,
we have a dedicated line already that can serve as the error
message, so paint it as a whitespace error message.

Also teach "git diff --check" to notice incomplete lines as
whitespace errors and report when incomplete-line whitespace error
class is in effect.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoapply: check and fix incomplete lines
Junio C Hamano [Wed, 12 Nov 2025 22:02:56 +0000 (14:02 -0800)]
apply: check and fix incomplete lines

The final line of a file that lacks the terminating newline at its
end is called an incomplete line.  In general they are frowned upon
for many reasons (imagine concatenating two files with "cat A B" and
what happens when A ends in an incomplete line, for example), and
text-oriented tools often mishandle such a line.

Implement checks in "git apply" for incomplete lines, which is off
by default for backward compatibility's sake, so that "git apply
--whitespace={fix,warn,error}" can notice, warn against, and fix
them.

As one of the new test shows, if you modify contents on an
incomplete line in the original and leave the resulting line
incomplete, it is still considered a whitespace error, the reasoning
being that "you'd better fix it while at it if you are making a
change on an incomplete line anyway", which may controversial.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agowhitespace: allocate a few more bits and define WS_INCOMPLETE_LINE
Junio C Hamano [Wed, 12 Nov 2025 22:02:55 +0000 (14:02 -0800)]
whitespace: allocate a few more bits and define WS_INCOMPLETE_LINE

Reserve a few more bits in the diff flags word to be used for future
whitespace rules.  Add WS_INCOMPLETE_LINE without implementing the
behaviour (yet).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoapply: revamp the parsing of incomplete lines
Junio C Hamano [Wed, 12 Nov 2025 22:02:54 +0000 (14:02 -0800)]
apply: revamp the parsing of incomplete lines

A patch file represents the incomplete line at the end of the file
with two lines, one that is the usual "context" with " " as the
first letter, "added" with "+" as the first letter, or "removed"
with "-" as the first letter that shows the content of the line,
plus an extra "\ No newline at the end of file" line that comes
immediately after it.

Ever since the apply machinery was written, the "git apply"
machinery parses "\ No newline at the end of file" line
independently, without even knowing what line the incomplete-ness
applies to, simply because it does not even remember what the
previous line was.

This poses a problem if we want to check and warn on an incomplete
line.  Revamp the code that parses a fragment, to actually drop the
'\n' at the end of the incoming patch file that terminates a line,
so that check_whitespace() calls made from the code path actually
sees an incomplete as incomplete.

Note that the result of this parsing is not directly used by the
code path that applies the patch.  apply_one_fragment() function
already checks if each of the patch text it handles is followed by a
line that begins with a backslash to drop the newline at the end of
the current line it is looking at.  In a sense, this patch harmonizes
the behaviour of the parsing side to what is already done in the
application side.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodiff: update the way rewrite diff handles incomplete lines
Junio C Hamano [Wed, 12 Nov 2025 22:02:53 +0000 (14:02 -0800)]
diff: update the way rewrite diff handles incomplete lines

The diff_symbol based output framework uses one DIFF_SYMBOL_* enum
value per the kind of output lines of "git diff", which corresponds
to one output line from the xdiff machinery used internally.  Most
notably, DIFF_SYMBOL_PLUS and DIFF_SYMBOL_MINUS that correspond to
"+" and "-" lines are designed to always take a complete line, even
if the output from xdiff machinery may produce "\ No newline at the
end of file" immediately after them.

But this is not true in the rewrite-diff codepath, which completely
bypasses the xdiff machinery.  Since the code path feeds the bytes
directly from the payload to the output routines, the output layer
has to deal with an incomplete line with DIFF_SYMBOL_PLUS and
DIFF_SYMBOL_MINUS, which never would see an incomplete line in the
normal code paths.  This lack of final newline is compensated by an
ugly hack for a fabricated DIFF_SYMBOL_NO_LF_EOF token to inject an
extra newline to the output to simulate output coming from the xdiff
machinery.

Revamp the way the complete-rewrite code path feeds the lines to the
output layer by treating the last line of the pre/post image when it
is an incomplete line specially.

This lets us remove the DIFF_SYMBOL_NO_LF_EOF hack and use the usual
DIFF_SYMBOL_CONTEXT_INCOMPLETE code path, which will later learn how
to handle whitespace errors.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodiff: call emit_callback ecbdata everywhere
Junio C Hamano [Wed, 12 Nov 2025 22:02:52 +0000 (14:02 -0800)]
diff: call emit_callback ecbdata everywhere

Everybody else, except for emit_rewrite_lines(), calls the
emit_callback data ecbdata.  Make sure we call the same thing by
the same name for consistency.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodiff: refactor output of incomplete line
Junio C Hamano [Wed, 12 Nov 2025 22:02:51 +0000 (14:02 -0800)]
diff: refactor output of incomplete line

Create a helper function that reacts to "\ No newline at the end of
file" in preparation for unifying the incomplete line handling in
the code path that handles xdiff output and the code path that
bypasses xdiff and produces a complete-rewrite patch.

Currently the output from the DIFF_SYMBOL_CONTEXT_INCOMPLETE case
still (ab)uses the same code as what is used for context lines, but
that would change in a later step where we introduce support to treat
an incomplete line as a whitespace error.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodiff: keep track of the type of the last line seen
Junio C Hamano [Wed, 12 Nov 2025 22:02:50 +0000 (14:02 -0800)]
diff: keep track of the type of the last line seen

The "\ No newline at the end of the file" can come after any of the
"-" (deleted preimage line), " " (unchanged line), or "+" (added
postimage line).  In later steps in this series, we will start
treating a change that makes a file to end in an incomplete line
as a whitespace error, and we would need to know what the previous
line was when we react to "\ No newline" in the diff output.  If
the previous line was a context (i.e., unchanged) line, the file
lacked the final newline before the change, and the change did not
touch that line and left it still incomplete, so we do not want to
warn in such a case.

Teach fn_out_consume() function to keep track of what the previous
line was, and prepare an otherwise empty switch statement to let us
react differently to "\ No newline" based on that.

Note that there is an existing curiosity (read: likely to be a bug)
in the code that increments line number in the preimage file every
time it sees a line with "\ No newline" on it, regardless of what
the previous line was.  I left it as-is, because it does not affect
the main theme of this series, and more importantly, I do not think
it matters, as these numbers are used only to compare them with
blank_at_eof_in_{pre,post}image to issue a warning when we see more
empty line was added at the end, but by definition, after we see
"\ No newline at the end of the file" for an added line, we will not
see an added line for the file.

An independent audit to ensure that this curious increment can be
safely removed would make a good #leftoverbits clean-up (we may even
find some code that decrements this counter or over-increments the
other quantity this counter is compared with that compensates the
effect of this curious increment that hides a bug, in which case we
may also need to remove them).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodiff: correct suppress_blank_empty hack
Junio C Hamano [Wed, 12 Nov 2025 22:02:49 +0000 (14:02 -0800)]
diff: correct suppress_blank_empty hack

The suppress-blank-empty feature abused the CONTEXT_INCOMPLETE
symbol that was meant to be used only for "\ No newline at the end
of file" code path.

The intent of the feature was to turn a context line we receive from
xdiff machinery (which always uses ' ' for context lines, even an
empty one) and spit it out as a truly empty line.

Perform such a conversion very locally at where a line from xdiff
that begins with ' ' is handled for output; there are many checks
before the control reaches such place that checks the first letter
of the diff output line to see if it is a context line, and having
to check for '\n' and treat it as a special case is error prone.

In order to catch similar hacks in the future, make sure the code
path that is meant for "\ No newline" case checks the first byte is
indeed a backslash.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodiff: emit_line_ws_markup() if/else style fix
Junio C Hamano [Wed, 12 Nov 2025 22:02:48 +0000 (14:02 -0800)]
diff: emit_line_ws_markup() if/else style fix

Apply the simple rule: if you need {} in one arm of the if/else
if/else... cascade, have {} in all of them.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agowhitespace: correct bit assignment comments
Junio C Hamano [Wed, 12 Nov 2025 22:02:47 +0000 (14:02 -0800)]
whitespace: correct bit assignment comments

A comment in diff.c claimed that bits up to 12th (counting from 0th)
are whitespace rules, and 13th thru 15th are for new/old/context,
but it turns out it was miscounting.  Correct them, and clarify
where the whitespace rule bits come from in the comment.  Extend bit
assignment comments to cover bits used for color-moved, which
weren't described.

Also update the way these bit constants are defined to use (1 << N)
notation, instead of octal constants, as it tends to make it easier
to notice a breakage like this.

Sprinkle a few blank lines between logically distinct groups of CPP
macro definitions to make them easier to read.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agodoc: add an explanation of Git's data model
Julia Evans [Wed, 12 Nov 2025 19:53:20 +0000 (19:53 +0000)]
doc: add an explanation of Git's data model

Git very often uses the terms "object", "reference", or "index" in its
documentation.

However, it's hard to find a clear explanation of these terms and how
they relate to each other in the documentation. The closest candidates
currently are:

1. `gitglossary`. This makes a good effort, but it's an alphabetically
    ordered dictionary and a dictionary is not a good way to learn
    concepts. You have to jump around too much and it's not possible to
    present the concepts in the order that they should be explained.
2. `gitcore-tutorial`. This explains how to use the "core" Git commands.
   This is a nice document to have, but it's not necessary to learn how
   `update-index` works to understand Git's data model, and we should
   not be requiring users to learn how to use the "plumbing" commands
   if they want to learn what the term "index" or "object" means.
3. `gitrepository-layout`. This is a great resource, but it includes a
   lot of information about configuration and internal implementation
   details which are not related to the data model. It also does
   not explain how commits work.

The result of this is that Git users (even users who have been using
Git for 15+ years) struggle to read the documentation because they don't
know what the core terms mean, and it's not possible to add links
to help them learn more.

Add an explanation of Git's data model. Some choices I've made in
deciding what "core data model" means:

1. Omit pseudorefs like `FETCH_HEAD`, because it's not clear to me
   if those are intended to be user facing or if they're more like
   internal implementation details.
2. Don't talk about submodules other than by mentioning how they
   relate to trees. This is because Git has a lot of special features,
   and explaining how they all work exhaustively could quickly go
   down a rabbit hole which would make this document less useful for
   understanding Git's core behaviour.
3. Don't discuss the structure of a commit message
   (first line, trailers etc).
4. Don't mention configuration.
5. Don't mention the `.git` directory, to avoid getting too much into
   implementation details

Signed-off-by: Julia Evans <julia@jvns.ca>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 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

6 weeks agoattr: avoid recursion when expanding attribute macros
Jeff King [Tue, 11 Nov 2025 22:36:47 +0000 (17:36 -0500)]
attr: avoid recursion when expanding attribute macros

Given a set of attribute macros like:

   [attr]a1 a2
   [attr]a2 a3
   ...
   [attr]a300000 -text
   file a1

expanding the attributes for "file" requires expanding "a1" to "a2",
"a2" to "a3", and so on until hitting a non-macro expansion ("-text", in
this case). We implement this via recursion: fill_one() calls
macroexpand_one(), which then recurses back to fill_one(). As a result,
very deep macro chains like the one above can run out of stack space and
cause us to segfault.

The required stack space is fairly small; I needed on the order of
200,000 entries to get a segfault on Linux. So it's unlikely anybody
would hit this accidentally, leaving only malicious inputs. There you
can easily construct a repo which will segfault on clone (we look at
attributes during the checkout step, but you'd see the same trying to do
other operations, like diff in a bare repo). It's mostly harmless, since
anybody constructing such a repo is only preventing victims from cloning
their evil garbage, but it could be a nuisance for hosting sites.

One option to prevent this is to limit the depth of recursion we'll
allow. This is conceptually easy to implement, but it raises other
questions: what should the limit be, and do we need a configuration knob
for it?

The recursion here is simple enough that we can avoid those questions by
just converting it to iteration instead. Rather than iterate over the
states of a match_attr in fill_one(), we'll put them all in a queue, and
the expansion of each can add to the queue rather than recursing. Note
that this is a LIFO queue in order to keep the same depth-first order we
did with the recursive implementation. I've avoided using the word
"stack" in the code because the term is already heavily used to refer to
the stack of .gitattribute files that matches the tree structure of the
repository.

The test uses a limited stack size so we can trigger the problem with a
much smaller input than the one shown above. The value here (3000) is
enough to trigger the issue on my x86_64 Linux machine.

Reported-by: Ben Stav <benstav@miggo.io>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoGit 2.52-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>
6 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

6 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

6 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

6 weeks ago.gitattributes: remove misspelled no-op whitespace attribute
Junio C Hamano [Tue, 11 Nov 2025 18:41:20 +0000 (10:41 -0800)]
.gitattributes: remove misspelled no-op whitespace attribute

Ever since 14f9e128 (Define the project whitespace policy,
2008-02-10) added the whitespace rules to .gitattributes, we spelled
the most general rule like so:

    * whitespace=!indent,trail,space

in the top-level .gitattributes file.  The intent of this line was
described in the commit log message:

     - Unless otherwise specified, indent with SP that could be
       replaced with HT are not "bad".  But SP before HT in the
       indent is "bad", and trailing whitespaces are "bad".

It clearly wanted to disable indent-with-non-tab, so !indent is most
likely a misspelt form of '-indent'.  Because indent-with-non-tab
has never been enabled by default, by luck this was not causing any
ill effect.

We could either remove "!indent", or spell it "-indent".  The
immediate effect would be the same.  It would only start to make a
difference when/if we enable indent-with-non-tab by default in
future versions of Git.

Let's take the former option to remove "!indent" from the list.  We
would feel the effect first-hand ourselves before anybody else if we
ever decide to change the built-in default whitespace rules, which
would be hidden from us if we decide to rewrite it to "-indent"
instead.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 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>
6 weeks agomaintenance: add 'is-needed' subcommand
Karthik Nayak [Sat, 8 Nov 2025 21:51:57 +0000 (22:51 +0100)]
maintenance: add 'is-needed' subcommand

The 'git-maintenance(1)' command provides tooling to run maintenance
tasks over Git repositories. The 'run' subcommand, as the name suggests,
runs the maintenance tasks. When used with the '--auto' flag, it uses
heuristics to determine if the required thresholds are met for running
said maintenance tasks.

There is however a lack of insight into these heuristics. Meaning, the
checks are linked to the execution.

Add a new 'is-needed' subcommand to 'git-maintenance(1)' which allows
users to simply check if it is needed to run maintenance without
performing it.

This subcommand can check if it is needed to run maintenance without
actually running it. Ideally it should be used with the '--auto' flag,
which would allow users to check if the thresholds required are met. The
subcommand also supports the '--task' flag which can be used to check
specific maintenance tasks.

While adding the respective tests in 't/t7900-maintenance.sh', remove a
duplicate of the test: 'worktree-prune task with --auto honors
maintenance.worktree-prune.auto'.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agomaintenance: add checking logic in `pack_refs_condition()`
Karthik Nayak [Sat, 8 Nov 2025 21:51:56 +0000 (22:51 +0100)]
maintenance: add checking logic in `pack_refs_condition()`

The 'git-maintenance(1)' command supports an '--auto' flag. Usage of the
flag ensures to run maintenance tasks only if certain thresholds are
met. The heuristic is defined on a task level, wherein each task defines
an 'auto_condition', which states if the task should be run.

The 'pack-refs' task is hard-coded to return 1 as:
1. There was never a way to check if the reference backend needs to be
optimized without actually performing the optimization.
2. We can pass in the '--auto' flag to 'git-pack-refs(1)' which would
optimize based on heuristics.

The previous commit added a `refs_optimize_required()` function, which
can be used to check if a reference backend required optimization. Use
this within `pack_refs_condition()`.

This allows us to add a 'git maintenance is-needed' subcommand which can
notify the user if maintenance is needed without actually performing the
optimization. Without this change, the reference backend would always
state that optimization is needed.

Since we import 'revision.h', we need to remove the definition for
'SEEN' which is duplicated in the included header.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agorefs: add a `optimize_required` field to `struct ref_storage_be`
Karthik Nayak [Sat, 8 Nov 2025 21:51:55 +0000 (22:51 +0100)]
refs: add a `optimize_required` field to `struct ref_storage_be`

To allow users of the refs namespace to check if the reference backend
requires optimization, add a new field `optimize_required` field to
`struct ref_storage_be`. This field is of type `optimize_required_fn`
which is also introduced in this commit.

Modify the debug, files, packed and reftable backend to implement this
field. A following commit will expose this via 'git pack-refs' and 'git
refs optimize'.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoreftable/stack: add function to check if optimization is required
Karthik Nayak [Sat, 8 Nov 2025 21:51:54 +0000 (22:51 +0100)]
reftable/stack: add function to check if optimization is required

The reftable backend performs auto-compaction as part of its regular
flow, which is required to keep the number of tables part of a stack at
bay. This allows it to stay optimized.

Compaction can also be triggered voluntarily by the user via the 'git
pack-refs' or the 'git refs optimize' command. However, currently there
is no way for the user to check if optimization is required without
actually performing it.

Extract out the heuristics logic from 'reftable_stack_auto_compact()'
into an internal function 'update_segment_if_compaction_required()'.
Then use this to add and expose `reftable_stack_compaction_required()`
which will allow users to check if the reftable backend can be
optimized.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 weeks agoreftable/stack: return stack segments directly
Karthik Nayak [Sat, 8 Nov 2025 21:51:53 +0000 (22:51 +0100)]
reftable/stack: return stack segments directly

The `stack_table_sizes_for_compaction()` function returns individual
sizes of each reftable table. This function is only called by
`reftable_stack_auto_compact()` to decide which tables need to be
compacted, if any.

Modify the function to directly return the segments, which avoids the
extra step of receiving the sizes only to pass it to
`suggest_compaction_segment()`.

A future commit will also add functionality for checking whether
auto-compaction is necessary without performing it. This change allows
code re-usability in that context.

Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
6 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>
6 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>
6 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>
7 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>
7 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

7 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

7 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

7 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

7 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>
7 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`

7 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>
7 weeks agogitk: add external diff file rename detection
Tobias Boesch [Thu, 6 Nov 2025 14:42:11 +0000 (14:42 +0000)]
gitk: add external diff file rename detection

If a file is renamed between commits and an external diff is started
through gitk on the original or the renamed file name,
gitk is unable to open the renamed file in the external diff editor.
It fails to fetch the renamed file from git, because it fetches it
using its original path in contrast to using the renamed path of the
file.
Detect the rename and open the external diff with the original and
the renamed file instead of no file (fetch the renamed file path and
name from git) no matter if the original or the renamed file is
selected in gitk.

Signed-off-by: Tobias Boesch <tobias.boesch@miele.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
7 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>
7 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>
7 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>