From 85704eda1820b350a9916b17d6d25fa33f68207d Mon Sep 17 00:00:00 2001 From: Pushkar Singh Date: Tue, 9 Jun 2026 13:47:42 +0000 Subject: [PATCH 01/12] transport-helper: fix TSAN race in transfer_debug() Currently, transfer_debug() lazily initializes a static variable based on GIT_TRANSLOOP_DEBUG. Since the function may be called from multiple worker threads, this initialization is racy and is therefore suppressed in .tsan-suppressions. Initialize the variable in bidirectional_transfer_loop() before any worker threads or processes are created. This patch removes the race and allows dropping the corresponding TSAN suppression. Signed-off-by: Pushkar Singh Signed-off-by: Junio C Hamano --- .tsan-suppressions | 1 - transport-helper.c | 19 ++++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.tsan-suppressions b/.tsan-suppressions index 5ba86d68459e61..d84883bd90f9a6 100644 --- a/.tsan-suppressions +++ b/.tsan-suppressions @@ -7,7 +7,6 @@ # A static variable is written to racily, but we always write the same value, so # in practice it (hopefully!) doesn't matter. race:^want_color$ -race:^transfer_debug$ # A boolean value, which tells whether the replace_map has been initialized or # not, is read racily with an update. As this variable is written to only once, diff --git a/transport-helper.c b/transport-helper.c index 4614036c99a5a0..8eee2de14bf205 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1343,24 +1343,18 @@ int transport_helper_init(struct transport *transport, const char *name) /* This should be enough to hold debugging message. */ #define PBUFFERSIZE 8192 +static int transfer_debug_enabled = -1; + /* Print bidirectional transfer loop debug message. */ __attribute__((format (printf, 1, 2))) static void transfer_debug(const char *fmt, ...) { - /* - * NEEDSWORK: This function is sometimes used from multiple threads, and - * we end up using debug_enabled racily. That "should not matter" since - * we always write the same value, but it's still wrong. This function - * is listed in .tsan-suppressions for the time being. - */ - va_list args; char msgbuf[PBUFFERSIZE]; - static int debug_enabled = -1; - if (debug_enabled < 0) - debug_enabled = getenv("GIT_TRANSLOOP_DEBUG") ? 1 : 0; - if (!debug_enabled) + if (transfer_debug_enabled < 0) + BUG("somebody forgot to check GIT_TRANSLOOP_DEBUG!"); + if (!transfer_debug_enabled) return; va_start(args, fmt); @@ -1630,6 +1624,9 @@ int bidirectional_transfer_loop(int input, int output) { struct bidirectional_transfer_state state; + if (transfer_debug_enabled < 0) + transfer_debug_enabled = getenv("GIT_TRANSLOOP_DEBUG") ? 1 : 0; + /* Fill the state fields. */ state.ptg.src = input; state.ptg.dest = 1; From 55088ac8a480d94ccf37bc53b6b2ddc7475b269b Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 10 Jun 2026 11:50:01 -0700 Subject: [PATCH 02/12] describe: limit default ref iteration to tags Without --all, git describe ignores refs outside refs/tags/. Commit 8a5a1884e9 (Avoid accessing non-tag refs in git-describe unless --all is requested, 2008-02-24) moved this check ahead of object lookup. That avoided loading objects for irrelevant refs, but the backend still has to yield every ref before get_name() can reject it. Pass refs/tags/ to the iterator so the backend can avoid visiting those refs in the first place. The new perf test creates 10,000 unrelated packed refs. It measures: git describe --exact-match HEAD The runtime drops from 0.03(0.01+0.01) to 0.02(0.00+0.00). In a repository with 120,532 refs but only 330 tags, the same command went from 171.7 ms to 9.9 ms. Signed-off-by: Tamir Duberstein Signed-off-by: Junio C Hamano --- builtin/describe.c | 3 +++ t/perf/p6100-describe.sh | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/builtin/describe.c b/builtin/describe.c index bffeed13a3cb14..e93c3720ec4bd7 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -740,6 +740,9 @@ int cmd_describe(int argc, return ret; } + if (!all) + for_each_ref_opts.prefix = "refs/tags/"; + hashmap_init(&names, commit_name_neq, NULL, 0); refs_for_each_ref_ext(get_main_ref_store(the_repository), get_name, NULL, &for_each_ref_opts); diff --git a/t/perf/p6100-describe.sh b/t/perf/p6100-describe.sh index 069f91ce493a70..b1c61529bb7bf8 100755 --- a/t/perf/p6100-describe.sh +++ b/t/perf/p6100-describe.sh @@ -27,4 +27,16 @@ test_perf 'describe HEAD with one tag' ' git describe --match=new HEAD ' +test_expect_success 'set up many unrelated refs' ' + ref_count=10000 && + git tag -m tip tip HEAD && + test_seq -f "create refs/heads/describe-perf/%05d HEAD" $ref_count | + git update-ref --stdin && + git pack-refs --all +' + +test_perf 'describe exact tag with many unrelated refs' ' + git describe --exact-match HEAD +' + test_done From e8f12e0e950a3735ccc2ed0bed2552ec1dcdd078 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 10 Jun 2026 14:39:08 -0700 Subject: [PATCH 03/12] t1400: have fifo test clean after itself One test in this script creates a pair of FIFOs, "in" and "out", that are named so generically that later tests may be tempted to use them. By the time those later tests run a command with its output redirected to the file (e.g., "git foobar >out"), however, nobody is reading from the lingering FIFO, and the test gets blocked forever. Clean them up when the test finishes. Signed-off-by: Junio C Hamano --- t/t1400-update-ref.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index db7f5444da2162..477af544bc2a46 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -1610,6 +1610,7 @@ test_expect_success 'transaction cannot restart ongoing transaction' ' ' test_expect_success PIPE 'transaction flushes status updates' ' + test_when_finished "rm -f in out" && mkfifo in out && (git update-ref --stdin out &) && From 3eb61fda62191dc12c2a215a3775bdab2ca7f1a6 Mon Sep 17 00:00:00 2001 From: Tuomas Ahola Date: Thu, 11 Jun 2026 19:19:44 +0300 Subject: [PATCH 04/12] doc: config: terminate runaway lists There are many places in git-config(1) where paragraphs that should logically come after a list are instead appended to the last item of the list. This is a well-documented quirk of AsciiDoc, and can be mitigated by enclosing the list in an open block: -- * first item * last item -- + New paragraph after the list. Fix the issue accordingly. Signed-off-by: Tuomas Ahola Signed-off-by: Junio C Hamano --- Documentation/config.adoc | 4 +++- Documentation/config/promisor.adoc | 2 ++ Documentation/config/safe.adoc | 2 ++ Documentation/git-config.adoc | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/config.adoc b/Documentation/config.adoc index dcea3c0c15e2a9..fc48c1c4618778 100644 --- a/Documentation/config.adoc +++ b/Documentation/config.adoc @@ -276,13 +276,15 @@ boolean:: When a variable is said to take a boolean value, many synonyms are accepted for 'true' and 'false'; these are all case-insensitive. - ++ +-- true;; Boolean true literals are `yes`, `on`, `true`, and `1`. Also, a variable defined without `= ` is taken as true. false;; Boolean false literals are `no`, `off`, `false`, `0` and the empty string. +-- + When converting a value to its canonical form using the `--type=bool` type specifier, 'git config' will ensure that the output is "true" or diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc index b0fa43b8393a53..39af63dcb87a32 100644 --- a/Documentation/config/promisor.adoc +++ b/Documentation/config/promisor.adoc @@ -63,11 +63,13 @@ If one of these field names (e.g., "token") is being checked for an advertised promisor remote (e.g., "foo"), three conditions must be met for the check of this specific field to pass: + +-- 1. The corresponding local configuration (e.g., `remote.foo.token`) must be set. 2. The server must advertise the "token" field for remote "foo". 3. The value of the locally configured `remote.foo.token` must exactly match the value advertised by the server for the "token" field. +-- + If any of these conditions is not met for any field name listed in `promisor.checkFields`, the advertised remote "foo" is rejected. diff --git a/Documentation/config/safe.adoc b/Documentation/config/safe.adoc index 2d45c98b12d951..5ae4476b24cbd7 100644 --- a/Documentation/config/safe.adoc +++ b/Documentation/config/safe.adoc @@ -2,10 +2,12 @@ safe.bareRepository:: Specifies which bare repositories Git will work with. The currently supported values are: + +-- * `all`: Git works with all bare repositories. This is the default. * `explicit`: Git only works with bare repositories specified via the top-level `--git-dir` command-line option, or the `GIT_DIR` environment variable (see linkgit:git[1]). +-- + If you do not use bare repositories in your workflow, then it may be beneficial to set `safe.bareRepository` to `explicit` in your global diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc index 00545b20542c60..8439ce97df95f2 100644 --- a/Documentation/git-config.adoc +++ b/Documentation/git-config.adoc @@ -221,6 +221,7 @@ Use `--no-value` to unset __. + Valid ``'s include: + +-- - 'bool': canonicalize values `true`, `yes`, `on`, and positive numbers as "true", and values `false`, `no`, `off` and `0` as "false". @@ -239,6 +240,7 @@ Valid ``'s include: escape sequence. When setting a value, a sanity-check is performed to ensure that the given value is canonicalize-able as an ANSI color, but it is written as-is. +-- + If the command is in `list` mode, then the `--type ` argument will apply to each listed config value. If the value does not successfully parse in that From 042221cccb3e750005f2b7f7002d3637662cb9c6 Mon Sep 17 00:00:00 2001 From: Tuomas Ahola Date: Thu, 11 Jun 2026 19:19:45 +0300 Subject: [PATCH 05/12] doc: config/sideband: fix description list delimiter Signed-off-by: Tuomas Ahola Signed-off-by: Junio C Hamano --- Documentation/config/sideband.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/config/sideband.adoc b/Documentation/config/sideband.adoc index 96fade7f5fee39..06de0d5c074566 100644 --- a/Documentation/config/sideband.adoc +++ b/Documentation/config/sideband.adoc @@ -9,7 +9,7 @@ sideband.allowControlCharacters:: `color`:: Allow ANSI color sequences, line feeds and horizontal tabs, but mask all other control characters. This is the default. - `cursor:`: + `cursor`:: Allow control sequences that move the cursor. This is disabled by default. `erase`:: From 4fa2c6e0457c5d00742f0cebded4f122f1dcd81a Mon Sep 17 00:00:00 2001 From: Tuomas Ahola Date: Thu, 11 Jun 2026 19:19:46 +0300 Subject: [PATCH 06/12] doc: git-config: escape erroneous highlight markup Paired octothorpes are used in AsciiDoc to mark highlighted text, being the equivalent HTML tag. To use the symbol as a literal character, it can be escaped with backticks. Do so in git-config.adoc. While at it, tweak the text slightly to make it scan better. Signed-off-by: Tuomas Ahola Signed-off-by: Junio C Hamano --- Documentation/git-config.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/git-config.adoc b/Documentation/git-config.adoc index 8439ce97df95f2..57af010ade5b5b 100644 --- a/Documentation/git-config.adoc +++ b/Documentation/git-config.adoc @@ -119,10 +119,10 @@ OPTIONS Append a comment at the end of new or modified lines. + If __ begins with one or more whitespaces followed -by "#", it is used as-is. If it begins with "#", a space is -prepended before it is used. Otherwise, a string " # " (a +by `#`, it is used as-is. If it begins with `#`, a space is +prepended before it is used. Otherwise, a string `" # "` (a space followed by a hash followed by a space) is prepended -to it. And the resulting string is placed immediately after +to it. The resulting string is placed immediately after the value defined for the variable. The __ must not contain linefeed characters (no multi-line comments are permitted). From 3f5203eeb46e6e01c7848acde4bf5a62d0dd7d1b Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 11 Jun 2026 21:31:51 -0700 Subject: [PATCH 07/12] ls-files: filter pathspec before lstat In --deleted and --modified modes, show_files() calls lstat() for each index entry before show_ce() applies the pathspec. prune_index() avoids most of these calls for pathspecs with a common directory prefix, but not for a top-level name or leading wildcard. Match before lstat() to avoid accessing the worktree for entries that cannot be shown. Treat this as a prefilter: do not update ps_matched, and retain the match in show_ce() so --error-unmatch is satisfied only by entries that the selected modes actually show. Prefilter only a single pathspec item, bounding the added work for each index entry. Applying match_pathspec() to multiple arguments can cost more than the lstat() calls it avoids. In a synthetic repository with 10,000 clean files, passing every path to ls-files --modified increased runtime from 112.5 ms to 494.1 ms when the prefilter was unconditional. With $parent and $this exported as paths to binaries built from the parent and this commit, on a repository with 881,290 index entries: hyperfine --warmup 0 --runs 3 \ --command-name parent \ '$parent -c core.fsmonitor=false ls-files --deleted -- README.md >/dev/null' \ --command-name this-commit \ '$this -c core.fsmonitor=false ls-files --deleted -- README.md >/dev/null' reported means of 65.790 seconds for the parent and 4.987 seconds for this commit. Link: https://lore.kernel.org/r/xmqqfr2tnfk0.fsf@gitster.g Helped-by: Jeff King Signed-off-by: Tamir Duberstein Signed-off-by: Junio C Hamano --- builtin/ls-files.c | 11 ++++++++++ t/meson.build | 1 + t/perf/p3010-ls-files.sh | 31 +++++++++++++++++++++++++++++ t/t3010-ls-files-killed-modified.sh | 18 +++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100755 t/perf/p3010-ls-files.sh diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 12d5d828ff581a..99e98fc187accb 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -453,6 +453,17 @@ static void show_files(struct repository *repo, struct dir_struct *dir) continue; if (ce_skip_worktree(ce)) continue; + /* + * match_pathspec() is linear in pathspec.nr, so prefilter only + * the single-pathspec case. Only entries shown by show_ce() + * satisfy --error-unmatch. + */ + if (pathspec.nr == 1 && + !match_pathspec(repo->index, &pathspec, fullname.buf, + fullname.len, max_prefix_len, NULL, + S_ISDIR(ce->ce_mode) || + S_ISGITLINK(ce->ce_mode))) + continue; stat_err = lstat(fullname.buf, &st); if (stat_err && (errno != ENOENT && errno != ENOTDIR)) error_errno("cannot lstat '%s'", fullname.buf); diff --git a/t/meson.build b/t/meson.build index c5832fee053561..3219264fe7d497 100644 --- a/t/meson.build +++ b/t/meson.build @@ -1141,6 +1141,7 @@ benchmarks = [ 'perf/p1500-graph-walks.sh', 'perf/p1501-rev-parse-oneline.sh', 'perf/p2000-sparse-operations.sh', + 'perf/p3010-ls-files.sh', 'perf/p3400-rebase.sh', 'perf/p3404-rebase-interactive.sh', 'perf/p4000-diff-algorithms.sh', diff --git a/t/perf/p3010-ls-files.sh b/t/perf/p3010-ls-files.sh new file mode 100755 index 00000000000000..ae14449432453b --- /dev/null +++ b/t/perf/p3010-ls-files.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='Tests ls-files worktree performance' + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +test_expect_success 'select a zero-prefix pathspec' ' + tracked_file=$(git ls-files | sed -n 1p) && + test -n "$tracked_file" && + pathspec="?${tracked_file#?}" && + test_export pathspec +' + +test_perf 'ls-files --deleted with pathspec' ' + git -c core.fsmonitor=false ls-files --deleted \ + -- "$pathspec" >/dev/null +' + +test_perf 'ls-files --deleted with all-matching pathspec' ' + git -c core.fsmonitor=false ls-files --deleted -- "*" >/dev/null +' + +test_perf 'ls-files --modified with pathspec' ' + git -c core.fsmonitor=false ls-files --modified \ + -- "$pathspec" >/dev/null +' + +test_done diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh index 7af4532cd1dfd0..6e38e10219e28e 100755 --- a/t/t3010-ls-files-killed-modified.sh +++ b/t/t3010-ls-files-killed-modified.sh @@ -124,4 +124,22 @@ test_expect_success 'validate git ls-files -m output.' ' test_cmp .expected .output ' +test_expect_success 'worktree modes honor wildcard pathspecs' ' + cat >.expected <<-\EOF && + path2/file2 + path3/file3 + EOF + git ls-files --deleted -- "path?/file?" >.output && + test_cmp .expected .output && + + cat >.expected <<-\EOF && + path7 + path8 + EOF + git ls-files --modified --error-unmatch -- "path[78]" >.output && + test_cmp .expected .output && + + test_must_fail git ls-files --modified --error-unmatch -- path10 +' + test_done From 689dc92e501e25ae1ed67410ff51b4359a4f5c3c Mon Sep 17 00:00:00 2001 From: Dominik Loidolt Date: Sat, 13 Jun 2026 14:27:09 +0200 Subject: [PATCH 08/12] compat/posix.h: enable UNUSED warning messages for Clang Use a dedicated Clang version check for the UNUSED macro. Commit 7c07f36ad2 (git-compat-util.h: GCC deprecated message arg only in GCC 4.5+, 2022-10-05) restricted use of the deprecated attribute's message argument in the UNUSED macro to GCC 4.5 or newer. Clang identifies itself as GNUC 4.2.1 for compatibility, so GIT_GNUC_PREREQ(4, 5) does not detect whether Clang supports the deprecated("...") form. Add GIT_CLANG_PREREQ() macro and use it to enable the UNUSED warning message for Clang 2.9 and newer. Signed-off-by: Dominik Loidolt Signed-off-by: Junio C Hamano --- compat/posix.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/compat/posix.h b/compat/posix.h index faaae1b6555d1b..273cb871013c6d 100644 --- a/compat/posix.h +++ b/compat/posix.h @@ -12,6 +12,9 @@ * ... code requiring gcc 2.8 or later ... * #endif * + * Note that Clang and other compilers define __GNUC__ for compatibility; use + * GIT_CLANG_PREREQ() to check for specific Clang versions. + * * This macro of course is not part of POSIX, but we need it for the UNUSED * macro which is used by some of our POSIX compatibility wrappers. */ @@ -22,6 +25,15 @@ #define GIT_GNUC_PREREQ(maj, min) 0 #endif +/* Similar for Clang. */ +#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_major__) +# define GIT_CLANG_PREREQ(maj, min) \ + ((__clang_major__ > (maj)) || \ + (__clang_major__ == (maj) && __clang_minor__ >= (min))) +#else +# define GIT_CLANG_PREREQ(maj, min) 0 +#endif + /* * UNUSED marks a function parameter that is always unused. It also * can be used to annotate a function, a variable, or a type that is @@ -35,7 +47,7 @@ * When a parameter may be used or unused, depending on conditional * compilation, consider using MAYBE_UNUSED instead. */ -#if GIT_GNUC_PREREQ(4, 5) +#if GIT_GNUC_PREREQ(4, 5) || GIT_CLANG_PREREQ(2, 9) #define UNUSED __attribute__((unused)) \ __attribute__((deprecated ("parameter declared as UNUSED"))) #elif defined(__GNUC__) From ffd45926dcb18337b7897bd96d8b1b14acec2359 Mon Sep 17 00:00:00 2001 From: Dominik Loidolt Date: Sat, 13 Jun 2026 14:27:10 +0200 Subject: [PATCH 09/12] compat/posix.h: clean up GIT_GNUC_PREREQ() and UNUSED Fix the preprocessor indentation of the GIT_GNUC_PREREQ() and UNUSED macros according to the CodingGuidelines, without changing their behavior. Adjust the spelling in the GIT_GNUC_PREREQ() comment block. Signed-off-by: Dominik Loidolt Signed-off-by: Junio C Hamano --- compat/posix.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compat/posix.h b/compat/posix.h index 273cb871013c6d..d2de5cedf5367e 100644 --- a/compat/posix.h +++ b/compat/posix.h @@ -5,11 +5,10 @@ /* * Derived from Linux "Features Test Macro" header - * Convenience macros to test the versions of gcc (or - * a compatible compiler). + * Convenience macros to test the versions of GCC (or a compatible compiler). * Use them like this: * #if GIT_GNUC_PREREQ (2,8) - * ... code requiring gcc 2.8 or later ... + * ... code requiring GCC 2.8 or later ... * #endif * * Note that Clang and other compilers define __GNUC__ for compatibility; use @@ -17,12 +16,12 @@ * * This macro of course is not part of POSIX, but we need it for the UNUSED * macro which is used by some of our POSIX compatibility wrappers. -*/ + */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) # define GIT_GNUC_PREREQ(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) #else - #define GIT_GNUC_PREREQ(maj, min) 0 +# define GIT_GNUC_PREREQ(maj, min) 0 #endif /* Similar for Clang. */ @@ -48,13 +47,13 @@ * compilation, consider using MAYBE_UNUSED instead. */ #if GIT_GNUC_PREREQ(4, 5) || GIT_CLANG_PREREQ(2, 9) -#define UNUSED __attribute__((unused)) \ - __attribute__((deprecated ("parameter declared as UNUSED"))) +# define UNUSED __attribute__((unused)) \ + __attribute__((deprecated("parameter declared as UNUSED"))) #elif defined(__GNUC__) -#define UNUSED __attribute__((unused)) \ +# define UNUSED __attribute__((unused)) \ __attribute__((deprecated)) #else -#define UNUSED +# define UNUSED #endif #ifdef __MINGW64__ From cf48887610da108a3fbc97645e2d2ba2e7178ad0 Mon Sep 17 00:00:00 2001 From: Dominik Loidolt Date: Sat, 13 Jun 2026 14:27:11 +0200 Subject: [PATCH 10/12] compat/posix.h: simplify GIT_GNUC_PREREQ() comparison GIT_GNUC_PREREQ() uses a glibc-style bit-shift version comparison, which is harder to read than an explicit major/minor comparison. Use an explicit comparison, as in many BSD headers, and drop the Linux header attribution comment because it no longer applies. Signed-off-by: Dominik Loidolt Signed-off-by: Junio C Hamano --- compat/posix.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compat/posix.h b/compat/posix.h index d2de5cedf5367e..2f01564b0d8a60 100644 --- a/compat/posix.h +++ b/compat/posix.h @@ -4,7 +4,6 @@ #define _FILE_OFFSET_BITS 64 /* - * Derived from Linux "Features Test Macro" header * Convenience macros to test the versions of GCC (or a compatible compiler). * Use them like this: * #if GIT_GNUC_PREREQ (2,8) @@ -19,7 +18,8 @@ */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) # define GIT_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) + ((__GNUC__ > (maj)) || \ + (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min))) #else # define GIT_GNUC_PREREQ(maj, min) 0 #endif From fbcc5408fcd60206234ba26cc103ef2757532ae0 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Sun, 14 Jun 2026 06:57:50 +0000 Subject: [PATCH 11/12] commit-graph: use timestamp_t for max parent generation accumulator compute_reachable_generation_numbers() computes each commit's generation as max(c->date, max(parent.generation)) + 1 by walking its parents and accumulating their generations into a local uint32_t max_gen = 0; while info->get_generation() returns timestamp_t and compute_generation_from_max() already takes its max_gen parameter as timestamp_t. For v1 (topological levels) the narrowing is harmless because GENERATION_NUMBER_V1_MAX is less than 2^30, but for v2 (corrected committer dates) it silently truncates any parent generation that does not fit in 32 bits, i.e. any parent whose committer timestamp is at or beyond 2106-02-07 UTC (>= 2^32). The truncated max then causes child commits to end up with a corrected committer date that matches the parent's instead of being at least 1 higher. The bad value gets written into the commit-graph and causes problems later, and can be noticed by running `git commit-graph verify`. Widen the accumulator to timestamp_t. This is solely an in-memory arithmetic fix with no on-disk format change: the on-disk format already encodes timestamp_t values and existing readers handle them unchanged. This merely allows the code to compute the correct value to write to disk. The narrowing was introduced in 80c928d947c2 (commit-graph: simplify compute_generation_numbers(), 2023-03-20), which rewired v2 to use the shared compute_reachable_generation_numbers() helper; the helper's local accumulator had been declared uint32_t in the immediately preceding 368d19b0b7fa (commit-graph: refactor compute_topological_levels(), 2023-03-20) when only v1 was using it, where it was harmless. Add a new test with a future-dated parent and a present-day child; without the above fix, `git commit-graph verify` reports the descendant's stored generation as below parent + 1. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- commit-graph.c | 2 +- t/t5328-commit-graph-64bit-time.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/commit-graph.c b/commit-graph.c index 474454db73d094..ad0e5d13b15009 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -1636,7 +1636,7 @@ static void compute_reachable_generation_numbers( struct commit *current = list->item; struct commit_list *parent; int all_parents_computed = 1; - uint32_t max_gen = 0; + timestamp_t max_gen = 0; for (parent = current->parents; parent; parent = parent->next) { repo_parse_commit(info->r, parent->item); diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh index d8891e6a922463..bc651b69deeea4 100755 --- a/t/t5328-commit-graph-64bit-time.sh +++ b/t/t5328-commit-graph-64bit-time.sh @@ -74,6 +74,15 @@ test_expect_success 'single commit with generation data exceeding UINT32_MAX' ' git -C repo-uint32-max commit-graph verify ' +test_expect_success 'descendant of commit with date exceeding UINT32_MAX' ' + git init repo-uint32-max-descendant && + test_commit -C repo-uint32-max-descendant \ + --date "@4294967300 +0000" future-parent && + test_commit -C repo-uint32-max-descendant present-day-child && + git -C repo-uint32-max-descendant commit-graph write --reachable && + git -C repo-uint32-max-descendant commit-graph verify +' + test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds generation overflow' ' graph=.git/objects/info/commit-graph && test_when_finished "rm -rf $graph" && From 95e20213faefeb95df29277c58ac1980ab68f701 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 17 Jun 2026 11:09:50 -0700 Subject: [PATCH 12/12] Hopefully final batch before -rc2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.55.0.adoc | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Documentation/RelNotes/2.55.0.adoc b/Documentation/RelNotes/2.55.0.adoc index 37f7a610a29b09..ecc76177e84e7d 100644 --- a/Documentation/RelNotes/2.55.0.adoc +++ b/Documentation/RelNotes/2.55.0.adoc @@ -73,6 +73,9 @@ UI, Workflows & Features * "git rev-list" (and "git log" family of commands) learned a new "--max-count-oldest" that picks oldest N commits in the range instead of the usual newest. + * Various AsciiDoc markup fixes in 'git config' documentation and + related files to ensure lists and formatting are rendered correctly. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -208,6 +211,16 @@ Performance, Internal Implementation, Development Support etc. delta cache instead of immediately freeing them, letting the existing cache limit policy decide eviction. + * `git ls-files --modified` and `git ls-files --deleted` have been + optimized to filter with pathspec before calling lstat() when there is + only a single pathspec item, avoiding unnecessary filesystem access + for entries that will not be shown. + + * The UNUSED macro in 'compat/posix.h' has been updated to use a + newly introduced GIT_CLANG_PREREQ macro for compiler version + checks, and the existing GIT_GNUC_PREREQ macro has been modernized + to use explicit major/minor comparisons rather than bit-shifting. + Fixes since v2.54 ----------------- @@ -389,6 +402,24 @@ Fixes since v2.54 (e.g., a clean/smudge filter) fails to start. (merge 061a68e443 mm/subprocess-handshake-fix later to maint). + * The TSAN race in transfer_debug() within transport-helper.c has been + resolved by initializing the debug flag early in + bidirectional_transfer_loop() before spawning worker threads, allowing + the removal of a TSAN suppression. + (merge 85704eda18 ps/transport-helper-tsan-fix later to maint). + + * 'git describe' has been taught to pass the 'refs/tags/' prefix down to + the ref iterator when '--all' is not requested, avoiding unnecessary + iteration over non-tag refs. + (merge 55088ac8a4 td/describe-tag-iteration later to maint). + + * compute_reachable_generation_numbers() in commit-graph used a 32-bit + integer to accumulate parent generations, which is OK for generation + number v1 (topological levels), but with generation number v2 + (adjusted committer timestamps), it truncated timestamps beyond + 2106. Fixed by widening the accumulator to timestamp_t. + (merge fbcc5408fc en/commit-graph-timestamp-fix later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 80f4b802e9 ja/doc-difftool-synopsis-style later to maint). (merge b96490241e jc/doc-timestamps-in-stat later to maint). @@ -414,3 +445,4 @@ Fixes since v2.54 (merge d1b72b29e9 am/doc-tech-hash-typofix later to maint). (merge 014c454799 ak/typofixes later to maint). (merge 522ea8ef7d js/osxkeychain-build-wo-rust later to maint). + (merge e8f12e0e95 jc/t1400-fifo-cleanup later to maint).