Jeff King [Thu, 2 Apr 2026 04:15:14 +0000 (00:15 -0400)]
http: drop const to fix strstr() warning
In redact_sensitive_header(), a C23 implementation of libc will complain
that strstr() assigns the result from "const char *cookie" to "char
*semicolon".
Ultimately the memory is writable. We're fed a strbuf, generate a const
pointer "sensitive_header" within it using skip_iprefix(), and then
assign the result to "cookie". So we can solve this by dropping the
const from "cookie" and "sensitive_header".
However, this runs afoul of skip_iprefix(), which wants a "const char
**" for its out-parameter. We can solve that by teaching skip_iprefix()
the same "make sure out is at least as const as in" magic that we
recently taught to skip_prefix().
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:15:12 +0000 (00:15 -0400)]
range-diff: drop const to fix strstr() warnings
This is another case where we implicitly drop the "const" from a pointer
by feeding it to strstr() and assigning the result to a non-const
pointer. This is OK in practice, since the const pointer originally
comes from a writable source (a strbuf), but C23 libc implementations
have started to complain about it.
We do write to the output pointer, so it needs to remain non-const. We
can just switch the input pointer to also be non-const in this case. By
itself that would run into problems with calls to skip_prefix(), but
since that function has now been taught to match in/out constness
automatically, it just works without us doing anything further.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:15:10 +0000 (00:15 -0400)]
pkt-line: make packet_reader.line non-const
The "line" member of a packet_reader struct is marked as const. This
kind of makes sense, because it's not its own allocated buffer that
should be freed, and we often use const to indicate that. But it is
always writable, because it points into the non-const "buffer" member.
And we rely on this writability in places like send-pack and
receive-pack, where we parse incoming packet contents by writing NULs
over delimiters. This has traditionally worked because we implicitly
cast away the constness with strchr() like:
const char *head;
char *p;
head = reader->line;
p = strchr(head, ' ');
Since C23 libc provides a generic strchr() to detect this implicit
const removal, this now generate a compiler warning on some platforms
(like recent glibc).
We can fix it by marking "line" as non-const, as well as a few
intermediate variables (like "head" in the above example). Note that by
itself, switching to a non-const variable would cause problems with this
line in send-pack.c:
if (!skip_prefix(reader->line, "unpack ", &reader->line))
But due to our skip_prefix() magic introduced in the previous commit,
this compiles fine (both the in and out-parameters are non-const, so we
know it is safe).
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:15:07 +0000 (00:15 -0400)]
skip_prefix(): check const match between in and out params
The skip_prefix() function takes in a "const char *" string, and returns
via a "const char **" out-parameter that points somewhere in that
string. This is fine if you are operating on a const string, like:
const char *in = ...;
const char *out;
if (skip_prefix(in, "foo", &out))
...look at out...
It is also OK if "in" is not const but "out" is, as we add an implicit
const when we pass "in" to the function. But there's another case where
this is limiting. If we want both fields to be non-const, like:
it doesn't work. The compiler will complain about the type mismatch in
passing "&out" to a parameter which expects "const char **". So to make
this work, we have to do an explicit cast.
But such a cast is ugly, and also means that we run afoul of making this
mistake:
which causes us to write to the memory pointed by "in", which was const.
We can imagine these four cases as:
(1) const in, const out
(2) non-const in, const out
(3) non-const in, non-const out
(4) const in, non-const out
Cases (1) and (2) work now. We would like case (3) to work but it
doesn't. But we would like to catch case (4) as a compile error.
So ideally the rule is "the out-parameter must be at least as const as
the in-parameter". We can do this with some macro trickery. We wrap
skip_prefix() in a macro so that it has access to the real types of
in/out. And then we pass those parameters through another macro which:
1. Fails if the "at least as const" rule is not filled.
2. Casts to match the signature of the real skip_prefix().
There are a lot of ways to implement the "fails" part. You can use
__builtin_types_compatible_p() to check, and then either our
BUILD_ASSERT macros or _Static_assert to fail. But that requires some
conditional compilation based on compiler feature. That's probably OK
(the fallback would be to just cast without catching case 4). But we can
do better.
The macro I have here uses a ternary with a dead branch that tries to
assign "in" to "out", which should work everywhere and lets the compiler
catch the problem in the usual way. With an input like this:
foo.c: In function ‘bad_drop_const’:
foo.c:2:35: error: assignment discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
2 | ((const char **)(0 ? ((*(out) = (in)),(out)) : (out)))
| ^
foo.c:4:31: note: in expansion of macro ‘CONST_OUTPARAM’
4 | #define foo(in,out) foo((in), CONST_OUTPARAM((in), (out)))
| ^~~~~~~~~~~~~~
foo.c:23:9: note: in expansion of macro ‘foo’
23 | foo(x, y);
| ^~~
It's a bit verbose, but I think makes it reasonably clear what's going
on. Using BUILD_ASSERT_OR_ZERO() ends up much worse. Using
_Static_assert you can be a bit more informative, but that's not
something we use at all yet in our code-base (it's an old gnu-ism later
standardized in C11).
Our generic macro only works for "const char **", which is something we
could improve by using typeof(in). But that introduces more portability
questions, and also some weird corner cases (e.g., around implicit void
conversion).
This patch just introduces the concept. We'll make use of it in future
patches.
Note that we rename skip_prefix() to skip_prefix_impl() here, to avoid
expanding the macro when defining the function. That's not strictly
necessary since we could just define the macro after defining the inline
function. But that would not be the case for a non-inline function (and
we will apply this technique to them later, and should be consistent).
It also gives us more freedom about where to define the macro. I did so
right above the definition here, which I think keeps the relevant bits
together.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:15:05 +0000 (00:15 -0400)]
pseudo-merge: fix disk reads from find_pseudo_merge()
The goal of this commit was to fix a const warning when compiling
with new versions of glibc, but ended up untangling a much deeper
problem.
The find_pseudo_merge() function does a bsearch() on the "commits"
pointer of a pseudo_merge_map. This pointer ultimately comes from memory
mapped from the on-disk bitmap file, and is thus not writable.
The "commits" array is correctly marked const, but the result from
bsearch() is returned directly as a non-const pseudo_merge_commit
struct. Since new versions of glibc annotate bsearch() in a way that
detects the implicit loss of const, the compiler now warns.
My first instinct was that we should be returning a const struct. That
requires apply_pseudo_merges_for_commit() to mark its local pointer as
const. But that doesn't work! If the offset field has the high-bit set,
we look it up in the extended table via nth_pseudo_merge_ext(). And that
function then feeds our const struct to read_pseudo_merge_commit_at(),
which writes into it by byte-swapping from the on-disk mmap.
But I think this points to a larger problem with find_pseudo_merge(). It
is not just that the return value is missing const, but it is missing
that byte-swapping! And we know that byte-swapping is needed here,
because the comparator we use for bsearch() also calls our
read_pseudo_merge_commit_at() helper.
So I think the interface is all wrong here. We should not be returning a
pointer to a struct which was cast from on-disk data. We should be
filling in a caller-provided struct using the bytes we found,
byte-swapping the values.
That of course raises the dual question: how did this ever work, and
does it work now? The answer to the first part is: this code does not
seem to be triggered in the test suite at all. If we insert a BUG("foo")
call into apply_pseudo_merges_for_commit(), it never triggers.
So I think there is something wrong or missing from the test setup, and
this bears further investigation. Sadly the answer to the second part
("does it work now") is still "no idea". I _think_ this takes us in a
positive direction, but my goal here is mainly to quiet the compiler
warning. Further bug-hunting on this experimental feature can be done
separately.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:15:03 +0000 (00:15 -0400)]
find_last_dir_sep(): convert inline function to macro
The find_last_dir_sep() function is implemented as an inline function
which takes in a "const char *" and returns a "char *" via strrchr().
That means that just like strrchr(), it quietly removes the const from
our pointer, which could lead to accidentally writing to the resulting
string.
But C23 versions of libc (including recent glibc) annotate strrchr()
such that the compiler can detect when const is implicitly lost, and it
now complains about the call in this inline function.
We can't just switch the return type of the function to "const char *",
though. Some callers really do want a non-const string to be returned
(and are OK because they are feeding a non-const string into the
function).
The most general solution is for us to annotate find_last_dir_sep() in
the same way that is done for strrchr(). But doing so relies on using
C23 generics, which we do not otherwise require.
Since this inline function is wrapping a single call to strrchr(), we
can take a shortcut. If we implement it as a macro, then the original
type information is still available to strrchr(), and it does the check
for us.
Note that this is just one implementation of find_last_dir_sep(). There
is an alternate implementation in compat/win32/path-utils.h. It doesn't
suffer from the same warning, as it does not use strrchr() and just
casts away const explicitly. That's not ideal, and eventually we may
want to conditionally teach it the same C23 generic trick that strrchr()
uses. But it has been that way forever, and our goal here is just
quieting new warnings, not improving const-checking.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:15:01 +0000 (00:15 -0400)]
run-command: explicitly cast away constness when assigning to void
We do this:
char *equals = strchr(*e, '=');
which implicitly removes the constness from "*e" and cause the compiler
to complain. We never write to "equals", but later assign it to a
string_list util field, which is defined as non-const "void *".
We have to cast somewhere, but doing so at the assignment to util is the
least-bad place, since that is the source of the confusion. Sadly we are
still open to accidentally writing to the string via the util pointer,
but that is the cost of using void pointers, which lose all type
information.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:14:58 +0000 (00:14 -0400)]
pager: explicitly cast away strchr() constness
When we do:
char *cp = strchr(argv[i], '=');
it implicitly removes the constness from argv[i]. We need "cp" to remain
writable (since we overwrite it with a NUL). In theory we should be able
to drop the const from argv[i], because it is a sub-pointer into our
duplicated pager_env variable.
But we get it from split_cmdline(), which uses the traditional "const
char **" type for argv. This is overly limiting, but changing it would
be awkward for all the other callers of split_cmdline().
Let's do an explicit cast with a note about why it is OK. This is enough
to silence compiler warnings about the implicit const problems.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:14:56 +0000 (00:14 -0400)]
transport-helper: drop const to fix strchr() warnings
We implicitly drop the const from our "key" variable when we do:
char *p = strchr(key, ' ');
which causes compilation with some C23 versions of libc (notably recent
glibc) to complain.
We need "p" to remain writable, since we assign NUL over the space we
found. We can solve this by also making "key" writable. This works
because it comes from a strbuf, which is itself a writable string.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:14:51 +0000 (00:14 -0400)]
http: add const to fix strchr() warnings
The "path" field of a "struct repo" (a custom http-push struct, not to
be confused with "struct repository) is a pointer into a const argv
string, and is never written to.
The compiler does not traditionally complain about assigning from a
const pointer because it happens via strchr(). But with some C23 libc
versions (notably recent glibc), it has started to do so. Let's mark the
field as const to silence the warnings.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Thu, 2 Apr 2026 04:14:49 +0000 (00:14 -0400)]
convert: add const to fix strchr() warnings
C23 versions of libc (like recent glibc) may provide generic versions of
strchr() that match constness between the input and return value. The
idea being that the compiler can detect when it implicitly converts a
const pointer into a non-const one (which then emits a warning).
There are a few cases here where the result pointer does not need to be
non-const at all, and we should mark it as such. That silences the
warning (and avoids any potential problems with trying to write via
those pointers).
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano [Mon, 30 Mar 2026 20:57:02 +0000 (13:57 -0700)]
Merge branch 'jw/object-name-bitset-to-enum'
The unsigned integer that is used as an bitset to specify the kind
of branches interpret_branch_name() function has been changed to
use a dedicated enum type.
* jw/object-name-bitset-to-enum:
object-name: turn INTERPRET_BRANCH_* constants into enum values
Junio C Hamano [Mon, 30 Mar 2026 20:57:00 +0000 (13:57 -0700)]
Merge branch 'jw/apply-corrupt-location'
"git apply" now reports the name of the input file along with the
line number when it encounters a corrupt patch, and correctly
resets the line counter when processing multiple patch files.
* jw/apply-corrupt-location:
apply: report input location in binary and garbage patch errors
apply: report input location in header parsing errors
apply: report the location of corrupt patches
Junio C Hamano [Fri, 27 Mar 2026 18:00:02 +0000 (11:00 -0700)]
Merge branch 'kh/doc-interpret-trailers-1'
Doc updates.
* kh/doc-interpret-trailers-1:
interpret-trailers: use placeholder instead of *
doc: config: convert trailers section to synopsis style
doc: interpret-trailers: normalize and fill out options
doc: interpret-trailers: convert to synopsis style
Junio C Hamano [Tue, 24 Mar 2026 19:31:34 +0000 (12:31 -0700)]
Merge branch 'ps/upload-pack-buffer-more-writes'
Reduce system overhead "git upload-pack" spends on relaying "git
pack-objects" output to the "git fetch" running on the other end of
the connection.
* ps/upload-pack-buffer-more-writes:
builtin/pack-objects: reduce lock contention when writing packfile data
csum-file: drop `hashfd_throughput()`
csum-file: introduce `hashfd_ext()`
sideband: use writev(3p) to send pktlines
wrapper: introduce writev(3p) wrappers
compat/posix: introduce writev(3p) wrapper
upload-pack: reduce lock contention when writing packfile data
upload-pack: prefer flushing data over sending keepalive
upload-pack: adapt keepalives based on buffering
upload-pack: fix debug statement when flushing packfile data
Junio C Hamano [Tue, 24 Mar 2026 19:31:32 +0000 (12:31 -0700)]
Merge branch 'ps/history-split'
"git history" learned the "split" subcommand.
* ps/history-split:
builtin/history: implement "split" subcommand
builtin/history: split out extended function to create commits
cache-tree: allow writing in-memory index as tree
add-patch: allow disabling editing of hunks
add-patch: add support for in-memory index patching
add-patch: remove dependency on "add-interactive" subsystem
add-patch: split out `struct interactive_options`
add-patch: split out header from "add-interactive.h"
Junio C Hamano [Mon, 23 Mar 2026 16:20:31 +0000 (09:20 -0700)]
Merge branch 'bb/imap-send-openssl-4.0-prep'
"imap-send" used to use functions whose use is going to be removed
with OpenSSL 4.0; rewrite them using public API that has been
available since OpenSSL 1.1 since 2016 or so.
* bb/imap-send-openssl-4.0-prep:
imap-send: move common code into function host_matches()
imap-send: use the OpenSSL API to access the subject common name
imap-send: use the OpenSSL API to access the subject alternative names
Junio C Hamano [Sat, 21 Mar 2026 16:25:58 +0000 (09:25 -0700)]
Merge branch 'master' of https://github.com/j6t/git-gui
* 'master' of https://github.com/j6t/git-gui:
git-gui: grey out comment lines in commit message
git-gui: wire up "git-gui--askyesno" with Meson
git-gui: massage "git-gui--askyesno" with "generate-script.sh"
git-gui: prefer shell at "/bin/sh" with Meson
git-gui: fix use of GIT_CEILING_DIRECTORIES
git-gui: shift tabstops to account for the first column of patch text
Junio C Hamano [Sat, 21 Mar 2026 16:25:10 +0000 (09:25 -0700)]
Merge branch 'master' of https://github.com/j6t/gitk
* 'master' of https://github.com/j6t/gitk:
gitk: l10n: make PO headers identify the Gitk project
gitk: ignore generated POT file
gitk: i18n: use "Gitk" as package name in POT file
gitk: commit translation files without file information
gitk: support link color in the Preferences dialog
gitk: use config settings for head/tag colors
Johannes Sixt [Fri, 20 Mar 2026 08:23:32 +0000 (09:23 +0100)]
Merge branch 'jx/i18n-fix' of github.com:jiangxin/gitk
* 'jx/i18n-fix' of github.com:jiangxin/gitk:
gitk: l10n: make PO headers identify the Gitk project
gitk: ignore generated POT file
gitk: i18n: use "Gitk" as package name in POT file
Jeff King [Tue, 17 Mar 2026 23:02:23 +0000 (19:02 -0400)]
contrib/diff-highlight: do not highlight identical pairs
We pair lines for highlighting based on their position in the hunk. So
we should never see two identical lines paired, like:
-one
-two
+one
+something else
which would pair -one/+one, because that implies that the diff could
easily be shrunk by turning line "one" into context.
But there is (at least) one exception: removing a newline at the end of
a file will produce a diff like:
-foo
+foo
\No newline at end of file
And we will pair those two lines. As a result, we end up marking the
whole line, including the newline, as the shared prefix. And there's an
empty suffix.
The most obvious bug here is that when we try to print the highlighted
lines, we remove the trailing newline from the suffix, but do not bother
with the prefix (under the assumption that there had to be a difference
_somewhere_ in the line, and thus the prefix would not eat all the way
up to the newline). And so you get an extra line like:
-foo
+foo
\No newline at end of file
This is obviously ugly, but also causes interactive.diffFilter to
(rightly) complain that the input and output do not match their lines
1-to-1.
This could easily be fixed by chomping the prefix, too, but I think the
problem is deeper. For one, I suspect some of the other logic gets
confused by forming an array with zero-indexed element "3" in a
3-element array. But more importantly, we try not to highlight whole
lines, as there's nothing interesting to show there. So let's catch this
early in is_pair_interesting() and bail to our usual passthrough
strategy.
Reported-by: Scott Baker <scott@perturb.org> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jiang Xin [Thu, 19 Mar 2026 09:11:17 +0000 (17:11 +0800)]
gitk: l10n: make PO headers identify the Gitk project
Commit f697d08 (gitk: i18n: use "Gitk" as package name in POT file,
2026-03-19) updated the generated POT template to use "Gitk" in its
Project-Id-Version header. Several existing PO files still carry older
header values such as "git" or "git-gui", so they do not consistently
identify themselves as Gitk translations.
Update the Project-Id-Version field in all Gitk PO files so that they
identify the Gitk project consistently.
The "Project-Id-Version" field in the PO header helps tools identify
which project a PO file belongs to. For example, Git's
"git-po-helper" uses it to choose project-specific checks and POT
handling rules. Without this change, some Gitk PO files are
misidentified because their headers still refer to other projects.
Junio C Hamano [Thu, 19 Mar 2026 22:39:02 +0000 (15:39 -0700)]
cocci: strbuf.buf is never NULL
We recently noticed one old code from 19 years ago protecting
against an ancient strbuf convention that the .buf member can be
NULL for an empty strbuf. As that is no longer the case in the
modern codebase, let's catch such a construct.
Jiang Xin [Thu, 19 Mar 2026 09:08:47 +0000 (17:08 +0800)]
gitk: ignore generated POT file
"po/gitk.pot" is generated from the source for translation maintenance.
Ignore it in the working tree so regenerating the template does not
introduce unnecessary noise in `git status`.
Jiang Xin [Thu, 19 Mar 2026 09:06:25 +0000 (17:06 +0800)]
gitk: i18n: use "Gitk" as package name in POT file
Use "Gitk" instead of the placeholder "PACKAGE" in the header of the
generated po/gitk.pot file. In particular, the "Project-Id-Version"
field in the header entry should be set to:
"Project-Id-Version: Gitk\n"
New PO files generated from this POT file will inherit that package
name.
René Scharfe [Thu, 19 Mar 2026 16:24:40 +0000 (17:24 +0100)]
commit-reach: simplify cleanup of remaining bitmaps in ahead_behind ()
Don't bother extracting the last few remaining prio_queue items in
order when we only want to free their associated bitmaps; just iterate
over the item array.
Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano [Thu, 19 Mar 2026 16:54:56 +0000 (09:54 -0700)]
Merge branch 'ps/unit-test-c-escape-names.txt'
The unit test helper function was taught to use backslash +
mnemonic notation for certain control characters like "\t", instead
of octal notation like "\011".
Junio C Hamano [Thu, 19 Mar 2026 07:15:59 +0000 (00:15 -0700)]
rerere: update to modern representation of empty strbufs
Back when b4833a2c (rerere: Fix use of an empty strbuf.buf,
2007-09-26) was written, a freshly initialized empty strbuf
had NULL in its .buf member, with .len set to 0. The code this
patch touches in rerere.c was written to _fix_ the original code
that assumed that the .buf member is always pointing at a NUL-terminated
string, even for an empty string, which did not hold back then.
That changed in b315c5c0 (strbuf change: be sure ->buf is never ever
NULL., 2007-09-27), and it has again become safe to assume that .buf
is never NULL, and .buf[0] has '\0' for an empty string (i.e., a
strbuf with its .len member set to 0).
A funny thing is, this piece of code has been moved around from
builtin-rerere.c to rerere.c and also adjusted for updates to the
hash function API over the years, but nobody bothered to question
if this special casing for an empty strbuf was still necessary:
b4833a2c62 (rerere: Fix use of an empty strbuf.buf, 2007-09-26) 5b2fd95606 (rerere: Separate libgit and builtin functions, 2008-07-09) 9126f0091f (fix openssl headers conflicting with custom SHA1 implementations, 2008-10-01) c0f16f8e14 (rerere: factor out handle_conflict function, 2018-08-05) 0d7c419a94 (rerere: convert to use the_hash_algo, 2018-10-15) 0578f1e66a (global: adapt callers to use generic hash context helpers, 2025-01-31)
Finally get rid of the special casing that was unnecessary for the
last 19 years.
Every compilation unit in Git is expected to include "git-compat-util.h"
first, either directly or indirectly via "builtin.h". This header papers
over differences between platforms so that we can expect the typical
POSIX functions to exist. Furthermore, it provides functionality that we
end up using everywhere.
This header is thus quite heavy as a consequence. Preprocessing it as a
standalone unit via `clang -E git-compat-util.h` yields over 23,000
lines of code overall. Naturally, it takes quite some time to compile
all of this.
Luckily, this is exactly the kind of use case that precompiled headers
aim to solve: instead of recompiling it every single time, we compile it
once and then link the result into the executable. If include guards are
set up properly it means that the file won't need to be reprocessed.
Set up such a precompiled header for "git-compat-util.h" and wire it up
via Meson. This causes Meson to implicitly include the precompiled
header in all compilation units. With GCC and Clang for example this is
done via the "-include" statement [1].
This leads to a significant speedup when performing full builds:
Benchmark 1: ninja (rev = HEAD~)
Time (mean ± σ): 14.467 s ± 0.126 s [User: 248.133 s, System: 31.298 s]
Range (min … max): 14.195 s … 14.633 s 10 runs
Benchmark 2: ninja (rev = HEAD)
Time (mean ± σ): 10.307 s ± 0.111 s [User: 173.290 s, System: 23.998 s]
Range (min … max): 10.030 s … 10.433 s 10 runs
Summary
ninja (rev = HEAD) ran
1.40 ± 0.02 times faster than ninja (rev = HEAD~)
In the next commit we're about to introduce a precompiled header for
"git-compat-util.h". The consequence of this change is that we'll
implicitly include that header for every compilation unit that uses the
precompiled headers.
This is okay for our "normal" library sources and our builtins. But some
of our compatibility sources do not include the header on purpose, and
doing so would cause compilation errors.
Prepare for this change by splitting out compatibility sources into
their static library. Like this, we can selectively enable precompiled
headers for the library sources.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-compat-util.h: move warning infra to prepare for PCHs
The "git-compat-util.h" header is supposed to be the first header
included by every code compilation unit. As such, a subsequent commit
will start to precompile this header to speed up compilation of Git.
This will cause an issue though with the way that we have set up the
"-Wsign-compare" warnings. It is expected that any compilation unit that
fails with that compiler warning sets `DISABLE_SIGN_COMPARE_WARNINGS`
before including "git-compat-util.h". If so, we'll disable the warning
right away via a compiler pragma.
But with precompiled headers we do not know ahead of time whether the
code unit wants to disable those warnings, and thus we'll have to
precompile the header without defining `DISABLE_SIGN_COMPARE_WARNINGS`.
But as the pragma statement is wrapped by our include guards, the second
include of that file will not have the desired effect of disabling the
warnings anymore.
We could fix this issue by declaring a new macro that compilation units
are expected to invoke after having included the file. In retrospect,
that would have been the better way to handle this as it allows for
more flexibility: we could for example toggle the warning for specific
code blocks, only. But changing this now would require a bunch of
changes, and the churn feels excessive for what we gain.
Instead, prepare for the precompiled headers by moving the code outside
of the include guards.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
We have a bunch of scripts used by our different build systems that are
all located in the top-level directory. Now that we have introduced the
new "tools/" directory though we have a better home for them.
Move the scripts into the "tools/" directory.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib: move "update-unicode.sh" script into "tools/"
The "update-unicode.sh" script is used to update the unicode data
compiled into Git whenever a new version of the Unicode standard has
been released. As such, it is a natural part of our developer-facing
tooling, and its presence in "contrib/" is misleading.
Promote the script into the new "tools/" directory.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib: move "coverage-diff.sh" script into "tools/"
The "coverage-diff.sh" script can be used to get information about test
coverage fro the Git codebase. It is thus rather specific to our build
and test infrastructure and part of the developer-facing tooling. The
fact that this script is part of "contrib/" is thus rather misleading
and a historic wart.
Promote the tool into the new "tools/" directory.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib: move "coccinelle/" directory into "tools/"
The Coccinelle tool is an ingrained part of our build infrastructure. It
is executed by our CI to detect antipatterns and is used to detect
misuses of certain interfaces. It's presence in "contrib/" is thus
rather misleading.
Promote the configuration into the new "tools/" directory.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
According to its readme, the "contrib/" directory's main intent is to
collect stuff that is not an official part of Git, either because it is
too specialized or because it is still considered experimental. The
reality tells a bit of a different story though: while it _does_ contain
such things, it also contains other things:
- Our credential helpers, which are being distributed by many
packagers nowadays and which can be considered "stable".
- A bunch of tooling that relates to our build and test
infrastructure.
Especially the second category is somewhat of a sore spot. You really
wouldn't expect build-related tooling to be considered an optional part
of Git. Quite the opposite.
Create a new top-level "tools/" directory to fix this discrepancy. This
directory will contain all kind of tools that are related to our build
infrastructure and that Git developers are likely to use day to day.
For now, this directory doesn't contain anything yet except for a
readme and a Meson skeleton. This will change in subsequent commits.
Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Aditya [Wed, 18 Mar 2026 20:07:35 +0000 (20:07 +0000)]
t2107: modernize path existence check
Replace '! test -f' with 'test_path_is_missing' to get better
debugging information by reporting loudly what expectation was
not met when the assertion fails.
Signed-off-by: Aditya <adityabnw07@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jialong Wang [Wed, 18 Mar 2026 19:09:42 +0000 (15:09 -0400)]
object-name: turn INTERPRET_BRANCH_* constants into enum values
Replace the INTERPRET_BRANCH_* preprocessor constants with enum
values and use that type where these flags are stored or passed
around.
These flags describe which kinds of branches may be considered during
branch-name interpretation, so represent them as an enum describing
branch kinds while keeping the existing bitmask semantics and
INTERPRET_BRANCH_* element names.
Signed-off-by: Jialong Wang <jerrywang183@yahoo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Mathias Rav [Wed, 11 Mar 2026 06:44:06 +0000 (06:44 +0000)]
merge-file: fix BUG when --object-id is used in a worktree
The `--object-id` option was added in commit e1068f0ad4
(merge-file: add an option to process object IDs, 2023-11-01)
together with a call to setup_git_directory() to avoid crashing
when run outside a repository.
However, the call to setup_git_directory() is redundant when run inside
a repository, as merge-file runs with RUN_SETUP_GENTLY, so the
repository has already been set up. The redundant call is harmless
when linked worktrees are not used, but in a linked worktree,
the repo_set_gitdir() function ends up being called twice.
Calling repo_set_gitdir() used to be silently accepted, but commit 2816b748e5 (odb: handle changing a repository's commondir, 2025-11-19)
changed this to a BUG in repository.c with the error message:
"cannot reinitialize an already-initialized object directory".
Guard the redundant call to setup_git_directory() behind a repo pointer
check, to ensure that we continue to give the correct "not a git repo"
error whilst avoiding the BUG when running in a linked worktree.
Signed-off-by: Mathias Rav <m@git.strova.dk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe [Tue, 17 Mar 2026 21:40:07 +0000 (22:40 +0100)]
use commit_stack instead of prio_queue in LIFO mode
A prio_queue with a NULL compare function acts as a stack -- the last
element in is the first one out (LIFO). Use an actual commit_stack
instead where possible, as it documents the behavior better, provides
type safety and saves some memory because prio_queue stores an
additional tie-breaking counter per element.
Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jialong Wang [Tue, 17 Mar 2026 16:23:21 +0000 (12:23 -0400)]
apply: report input location in binary and garbage patch errors
Several binary parsing paths in apply.c still report only line
numbers. When more than one patch input is fed to a single
invocation, that does not tell the user which input the line belongs
to.
Report the patch input location for corrupt and unrecognized binary
patches, as well as the "patch with only garbage" case, and update
the related tests.
Signed-off-by: Jialong Wang <jerrywang183@yahoo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jialong Wang [Tue, 17 Mar 2026 16:23:20 +0000 (12:23 -0400)]
apply: report input location in header parsing errors
Several header parsing errors in apply.c still report only line
numbers. When applying more than one input, that does not tell the
user which input the line belongs to.
Report the patch input location for these header parsing errors, and
update the related tests.
While touching parse_git_diff_header(), update the helper state to use
the current header line when reporting these errors.
Signed-off-by: Jialong Wang <jerrywang183@yahoo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jialong Wang [Tue, 17 Mar 2026 01:15:44 +0000 (21:15 -0400)]
t2203: avoid suppressing git status exit code
When git status is piped into grep, the exit status of the Git
command is hidden by the pipeline. Capture the status output in a
temporary file first, and then filter it as needed, so that any
failure from git status is still noticed by the test suite.
Signed-off-by: Jialong Wang <jerrywang183@yahoo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Eric Ju [Tue, 17 Mar 2026 02:36:24 +0000 (22:36 -0400)]
refs: add 'preparing' phase to the reference-transaction hook
The "reference-transaction" hook is invoked multiple times during a ref
transaction. Each invocation corresponds to a different phase:
- The "prepared" phase indicates that references have been locked.
- The "committed" phase indicates that all updates have been written to disk.
- The "aborted" phase indicates that the transaction has been aborted and that
all changes have been rolled back.
This hook can be used to learn about the updates that Git wants to perform.
For example, forges use it to coordinate reference updates across multiple
nodes.
However, the phases are insufficient for some specific use cases. The earliest
observable phase in the "reference-transaction" hook is "prepared", at which
point Git has already taken exclusive locks on every affected reference. This
makes it suitable for last-chance validation, but not for serialization. So by
the time a hook sees the "prepared" phase, it has no way to defer locking, and
thus it cannot rearrange multiple concurrent ref transactions relative to one
another.
Introduce a new "preparing" phase that runs before the "prepared" phase, that
is before Git acquires any reference lock on disk. This gives callers a
well-defined window to perform validation, enable higher-level ordering of
concurrent transactions, or reject the transaction entirely, all without
interfering with the locking state.
This change is strictly speaking not backwards compatible. Existing hook
scripts that do not know how to handle unknown phases may treat 'preparing'
as an error and return non-zero. But the hook is considered to expose
internal implementation details of how Git works, and as such we have
been a bit more lenient with changing its exact semantics, like for example
in a8ae923f85 (refs: support symrefs in 'reference-transaction' hook, 2024-05-07).
An alternative would be to introduce a "reference-transaction-v2" hook that
knows about the new phase. This feels like a rather heavy-weight option though,
and was thus discarded.
Helped-by: Patrick Steinhardt <ps@pks.im> Helped-by: Justin Tobler <jltobler@gmail.com> Helped-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Eric Ju <eric.peijian@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
doc: interpret-trailers: normalize and fill out options
Some negated options are missing according to
`git interpret-trailers -h`.
Also normalize to the “stuck form” (see gitcli(7)) like what was done
in 806337c7 (doc: notes: use stuck form throughout, 2025-05-27).[1]
Also normalize the order of the regular and negated options according to
the current convention.[2]
Also note that `--no-trailer` will reset the list.
† 1: See also https://lore.kernel.org/git/6f7d027e-088a-4d66-92af-b8d1c32d730c@app.fastmail.com/
† 2: https://lore.kernel.org/git/xmqqcyct1mtq.fsf@gitster.g/
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
doc: interpret-trailers: convert to synopsis style
See e.g. 0ae23ab5 (doc: convert git worktree to synopsis style,
2025-10-05) for the markup rules for this style.
There aren’t many subtleties to the transformation of this doc since it
doesn’t use any advanced constructs. The only thing is that "`:`{nbsp}" is
used instead of `': '` to refer to effective inline-verbatim with
a space (␠).[1] I also use (_) for emphasis although (') gives the
same result.
Also prefer linking to Git commands instead of saying e.g. `git
format-patch`. But for this command we can type out git-interpret-
trailers(1) to avoid a self-reference.
Also replace camel case `<keyAlias>` with kebab case `<key-alias>`.
And while doing that make sure to replace `trailer.*` with
`trailer.<key-alias>`.
† 1: Similar to "`tag:`{nbsp}" in `Documentation/pretty-formats.adoc`
Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King [Sat, 14 Mar 2026 16:08:14 +0000 (12:08 -0400)]
transport: plug leaks in transport_color_config()
We retrieve config values with repo_config_get_string(), which will
allocate a new copy of the string for us. But we don't hold on to those
strings, since they are just fed to git_config_colorbool() and
color_parse(). But nor do we free them, which means they leak.
We can fix this by using the "_tmp" form of repo_config_get_string(),
which just hands us a pointer directly to the internal storage. This is
OK for our purposes, since we don't need it to last for longer than our
parsing calls.
Two interesting side notes here:
1. Many types already have a repo_config_get_X() variant that handles
this for us (e.g., repo_config_get_bool()). But neither colorbools
nor colors themselves have such helpers. We might think about
adding them, but converting all callers is a larger task, and out
of scope for this fix.
2. As far as I can tell, this leak has been there since 960786e761
(push: colorize errors, 2018-04-21), but wasn't detected by LSan in
our test suite. It started triggering when we applied dd3693eb08
(transport-helper, connect: use clean_on_exit to reap children on
abnormal exit, 2026-03-12) which is mostly unrelated.
Even weirder, it seems to trigger only with clang (and not gcc),
and only with GIT_TEST_DEFAULT_REF_FORMAT=reftable. So I think this
is another odd case where the pointers happened to be hanging
around in stack memory, but changing the pattern of function calls
in nearby code was enough for them to be incidentally overwritten.
Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
PRASHANT S BISHT [Mon, 16 Mar 2026 17:24:57 +0000 (22:54 +0530)]
t4200: convert test -[df] checks to test_path_* helpers
Replace old-style path existence checks in t4200-rerere.sh with
the appropriate test_path_* helper functions. These helpers provide
clearer diagnostic messages on failure than the raw shell test
builtin.
Signed-off-by: Prashant S Bisht <prashantjee2025@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>