summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2026-04-06doc: convert git-range-diff manual page to synopsis styleJean-Noël Avila1-25/+25
* convert commands and options to synopsis style * use _<placeholder>_ for arguments * small style fixes Signed-off-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-06doc: convert git-difftool manual page to synopsis styleJean-Noël Avila3-56/+56
* convert commands to synopsis style * use _<placeholder>_ for arguments * fix conditional text to sentence limits Signed-off-by: Jean-Noël Avila <jn.avila@free.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-06backfill: auto-detect sparse-checkout from configTrieu Huynh2-1/+16
Commit 85127bcdea ("backfill: assume --sparse when sparse-checkout is enabled") intended for 'git backfill' to consult the repository configuration when the user does not pass '--sparse' or '--no-sparse' on the command line. It added the sentinel check: if (ctx->sparse < 0) ctx->sparse = cfg->apply_sparse_checkout; However, the ctx->sparse field is initialized to 0 instead of -1, so this guard never triggers. Consequently, the repository config (core.sparseCheckout) is never checked, and the command always performs a full backfill even when sparse-checkout is enabled. Fix this by initializing ctx->sparse to -1, ensuring the existing fallback logic correctly reads the repository configuration when no explicit flags are provided. Add a test to verify that 'git backfill' automatically respects sparse-checkout settings when no flags are passed. Signed-off-by: Trieu Huynh <vikingtc4@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-06git-compat-util: fix CONST_OUTPARAM typo and indentationJeff King1-2/+2
There's a typo in the comment, making it hard to understand. And the macro itself is indented with spaces rather than tab. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-04Merge branch 'master' of https://github.com/git/gitJiang Xin38-386/+1365
Upstream adds 18 new translatable messages. * 'master' of https://github.com/git/git: (41 commits) A bit more on top of 2.54-rc0 ... Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-03A couple more on top of -rc0Junio C Hamano1-0/+6
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-03Merge branch 'ps/dash-buggy-0.5.13-workaround'Junio C Hamano7-36/+54
The way dash 0.5.13 handles non-ASCII contents in here-doc is buggy and breaks our existing tests, which unfortunately have been rewritten to avoid triggering the bug. * ps/dash-buggy-0.5.13-workaround: t9300: work around partial read bug in Dash v0.5.13 t: work around multibyte bug in quoted heredocs with Dash v0.5.13
2026-04-03Merge branch 'js/cmake-needs-writev-compat-too'Junio C Hamano1-1/+5
Build instruction for recently added writev() compatibility wrapper has been also added to cmake. * js/cmake-needs-writev-compat-too: cmake: use writev(3p) wrapper as needed
2026-04-03Merge branch 'js/mingw-use-strftime-directly-in-ucrt-build'Junio C Hamano1-0/+4
MinGW build updates. * js/mingw-use-strftime-directly-in-ucrt-build: mingw: use strftime() directly in UCRT builds
2026-04-03A bit more on top of 2.54-rc0Junio C Hamano1-0/+11
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-03Merge branch 'th/t8003-unhide-git-failures'Junio C Hamano1-44/+31
Test clean-up. * th/t8003-unhide-git-failures: t8003: modernise style t8003: avoid suppressing git's exit code
2026-04-03Merge branch 'sa/replay-revert'Junio C Hamano7-99/+359
"git replay" (experimental) learns, in addition to "pick" and "replay", a new operating mode "revert". * sa/replay-revert: replay: add --revert mode to reverse commit changes sequencer: extract revert message formatting into shared function
2026-04-03Merge branch 'pw/worktree-reduce-the-repository'Junio C Hamano4-42/+20
Reduce the reference to the_repository in the worktree subsystem. * pw/worktree-reduce-the-repository: worktree: reject NULL worktree in get_worktree_git_dir() worktree add: stop reading ".git/HEAD" worktree: remove "the_repository" from is_current_worktree()
2026-04-03Merge branch 'ar/config-hook-cleanups'Junio C Hamano12-174/+423
Code clean-up around the recent "hooks defined in config" topic. * ar/config-hook-cleanups: hook: reject unknown hook names in git-hook(1) hook: show disabled hooks in "git hook list" hook: show config scope in git hook list hook: introduce hook_config_cache_entry for per-hook data t1800: add test to verify hook execution ordering hook: make consistent use of friendly-name in docs hook: replace hook_list_clear() -> string_list_clear_func() hook: detect & emit two more bugs hook: rename cb_data_free/alloc -> hook_data_free/alloc hook: fix minor style issues builtin/receive-pack: properly init receive_hook strbuf hook: move unsorted_string_list_remove() to string-list.[ch]
2026-04-03Merge branch 'ds/backfill-revs'Junio C Hamano7-10/+280
`git backfill` learned to accept revision and pathspec arguments. * ds/backfill-revs: t5620: test backfill's unknown argument handling path-walk: support wildcard pathspecs for blob filtering backfill: work with prefix pathspecs backfill: accept revision arguments t5620: prepare branched repo for revision tests revision: include object-name.h
2026-04-03Merge branch 'mf/format-patch-commit-list-format-doc'Junio C Hamano3-20/+15
Doc updates. * mf/format-patch-commit-list-format-doc: format-patch: removing unconditional wrapping docs: fix --commit-list-format related entries
2026-04-03Merge branch 'mf/format-patch-commit-list-format'Junio C Hamano7-53/+84
Improve the recently introduced `git format-patch --commit-list-format` (formerly `--cover-letter-format`) option, including a new "modern" preset and better CLI ergonomics. * mf/format-patch-commit-list-format: format-patch: --commit-list-format without prefix format-patch: add preset for --commit-list-format format-patch: wrap generate_commit_list_cover() format.commitListFormat: strip meaning from empty docs/pretty-formats: add %(count) and %(total) format-patch: rename --cover-letter-format option format-patch: refactor generate_commit_list_cover pretty.c: better die message %(count) and %(total)
2026-04-03Merge branch 'mf/format-patch-cover-letter-format'Junio C Hamano6-14/+212
"git format-patch --cover-letter" learns to use a simpler format instead of the traditional shortlog format to list its commits with a new --cover-letter-format option and format.commitListFormat configuration variable. * mf/format-patch-cover-letter-format: docs: add usage for the cover-letter fmt feature format-patch: add commitListFormat config format-patch: add ability to use alt cover format format-patch: move cover letter summary generation pretty.c: add %(count) and %(total) placeholders
2026-04-03mingw: use strftime() directly in UCRT buildsJohannes Schindelin1-0/+4
The `mingw_strftime()` wrapper exists to work around msvcrt.dll's incomplete `strftime()` implementation by dynamically loading the version from ucrtbase.dll at runtime via `LoadLibrary()` + `GetProcAddress()`. When the binary is already linked against UCRT (i.e. when building in the UCRT64 environment), the linked-in `strftime()` is the ucrtbase.dll version, making the dynamic loading needless churn: It's calling the very same code. Simply guard both the declaration and implementation so that the unnecessary work-around is skipped in UCRT builds. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-03cmake: use writev(3p) wrapper as neededJohannes Schindelin1-1/+5
This is a companion patch of 3b9b2c2a29a (compat/posix: introduce writev(3p) wrapper, 2026-03-13) where support for using the `writev()` wrapper was introduced in the `Makefile` and the Meson-based build, but the CMake build still needs that treatment, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-03l10n: document AI and PO helper in po/READMEJiang Xin1-6/+21
Document po/AGENTS.md-driven AI workflows (with an example prompt) before the PO helper section, cross-reference git-po-helper, and summarize quality checks plus optional agent integration in the PO helper section. Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-03l10n: docs: add review instructions in AGENTS.mdJiang Xin1-0/+197
Add a new "Reviewing po/XX.po" section to po/AGENTS.md that provides comprehensive guidance for AI agents to review translation files. Translation diffs lose context, especially for multi-line msgid and msgstr entries. Some LLMs ignore context and cannot evaluate translations accurately; others rely on scripts to search for context in source files, making the review process time-consuming. To address this, git-po-helper implements the compare subcommand, which extracts new or modified translations with full context (complete msgid/msgstr pairs), significantly improving review efficiency. A limitation is that the extracted content lacks other already-translated content for reference, which may affect terminology consistency. This is mitigated by including a glossary in the PO file header. git-po-helper-generated review files include the header entry and glossary (if present) by default. The review workflow leverages git-po-helper subcommands: - git-po-helper compare: Extract new or changed entries between two versions of a PO file into a valid PO file for review. Supports multiple modes: * Compare HEAD with the working tree (local changes) * Compare a commit's parent with the commit (--commit) * Compare a commit with the working tree (--since) * Compare two arbitrary revisions (-r) - git-po-helper msg-select: Split large review files into smaller batches by entry index range for manageable review sessions. Supports range formats like "-50" (first 50), "51-100", "101-" (to end). Evaluation with the Qwen model: git-po-helper agent-run review --commit 2000abefba --agent qwen Benchmark results: | Metric | Value | |------------------|----------------------------------| | Turns | 22 | | Input tokens | 537263 | | Output tokens | 4397 | | API duration | 167.84 s | | Review score | 96/100 | | Total entries | 63 | | With issues | 4 (1 critical, 2 major, 1 minor) | Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-03l10n: docs: add translation instructions in AGENTS.mdJiang Xin1-1/+600
Add a new "Translating po/XX.po" section to po/AGENTS.md with detailed workflow and procedures for AI agents to translate language-specific PO files. Users can invoke AI-assisted translation in coding tools with a prompt such as: "Translate the po/XX.po file by referring to @po/AGENTS.md" Translation results serve as drafts; human contributors must review and approve before submission. To address the low translation efficiency of some LLMs, batch translation replaces entry-by-entry translation. git-po-helper implements a gettext JSON format for translation files, replacing PO format during translation to enable batch processing. Evaluation with the Qwen model: git-po-helper agent-run --agent=qwen translate po/zh_CN.po Test translation (127 entries, 50 per batch): Initial state: 5998 translated, 91 fuzzy, 36 untranslated Final state: 6125 translated, 0 fuzzy, 0 untranslated Successfully translated: 127 entries (91 fuzzy + 36 untranslated) Success rate: 100% Benchmark results (3-run average): AI agent using gettext tools: | Metric | Value | |------------------|--------------------------------| | Avg. Num turns | 86 (176, 44, 40) | | Avg. Exec. Time | 20m44s (39m56s, 14m38s, 7m38s) | | Successful runs | 3/3 | AI agent using git-po-helper (JSON batch flow): | Metric | Value | |------------------|--------------------------------| | Avg. Num turns | 56 (68, 39, 63) | | Avg. Exec. Time | 19m8s (28m55s, 9m1s, 19m28s) | | Successful runs | 3/3 | The git-po-helper flow reduces the number of turns (86 → 56) with similar execution time; the bottleneck appears to be LLM processing rather than network interaction. Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-03l10n: docs: add update PO instructions in AGENTS.mdJiang Xin1-0/+11
Add a new section to po/AGENTS.md to provide clear instructions for updating language-specific PO files. The improved documentation significantly reduces both conversation turns and execution time. Performance evaluation with the Qwen model: # Before: instructions in po/README.md; the custom prompt # references po/README.md during execution git-po-helper agent-test --runs=5 --agent=qwen update-po \ --prompt="Update po/zh_CN.po according to po/README.md" # After: instructions in po/AGENTS.md; the built-in prompt # references po/AGENTS.md during execution git-po-helper agent-test --runs=5 --agent=qwen update-po Benchmark results (5-run average): | Metric | Before | After | Improvement | |-------------|---------|--------|-------------| | Turns | 22 | 4 | -82% | | Exec. time | 38s | 9s | -76% | | Turn range | 17-39 | 3-9 | | | Time range | 25s-68s | 7s-14s | | Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-03l10n: docs: add AGENTS.md with update POT instructionsJiang Xin1-0/+70
Add a new documentation file po/AGENTS.md that provides agent-specific instructions for generating or updating po/git.pot, separating them from the general po/README.md. This separation allows for more targeted optimization of AI agent workflows. Performance evaluation with the Qwen model: # Before: No agent-specific instructions; use po/README.md for # reference. git-po-helper agent-test --runs=5 --agent=qwen update-pot \ --prompt="Update po/git.pot according to po/README.md" # Phase 1: add the instructions to po/README.md; the prompt # references po/README.md during execution git-po-helper agent-test --runs=5 --agent=qwen update-pot \ --prompt="Update po/git.pot according to po/README.md" # Phase 2: add the instructions to po/AGENTS.md; use the built-in # prompt that references po/AGENTS.md during execution git-po-helper agent-test --runs=5 --agent=qwen update-pot Benchmark results (5-run average): Phase 1 - Optimizing po/README.md: | Metric | Before | Phase 1 | Improvement | |-------------|---------|---------|-------------| | Turns | 17 | 5 | -71% | | Exec. time | 34s | 14s | -59% | | Turn range | 3-36 | 3-7 | | | Time range | 10s-59s | 9s-19s | | Phase 2 - Adding po/AGENTS.md (further optimization): | Metric | Before | Phase 2 | Improvement | |-------------|---------|---------|-------------| | Turns | 17 | 3 | -82% | | Exec. time | 34s | 8s | -76% | | Turn range | 3-36 | 3-3 | | | Time range | 10s-59s | 6s-9s | | Separating agent-specific instructions into AGENTS.md provides: - More focused and concise instructions for AI agents - Cleaner README.md for human readers - An additional 11% reduction in turns and 17% reduction in execution time - More consistent behavior (turn range reduced from 3-7 to 3-3) Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-03l10n: add .gitattributes to simplify location filteringJiang Xin6-119/+161
To simplify the location filtering process for l10n contributors when committing po/XX.po files, add filter attributes for selected PO files to the repository. This ensures all contributors automatically get the same filter configuration without manual setup in .git/info/attributes. The default filter (gettext-no-location) is applied to all .po files except: - Legacy, unmaintained PO files that still contain location comments. Leaving the filter off avoids index vs working-tree discrepancies for these files. The CI pipeline will report an error when future updates touch these legacy files. - Some PO files use a different filter that strips only line numbers from location comments while keeping filenames. Contributors still need to manually define the filter drivers via git-config as documented in po/README.md. Four PO files that use location filtering (po/ca.po, po/es.po, po/ga.po, po/ru.po) were batch-modified so their on-disk format matches the filter output (e.g. line wrapping), avoiding index vs working-tree mismatch. Additionally, po/README.md has been reorganized: the material on preparing location-less PO files for commit has been moved from "Updating a XX.po file" to a separate "Preparing a XX.po file for commit" section. This prevents AI agents from introducing unrelated operations when updating PO files. Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2026-04-02t9300: work around partial read bug in Dash v0.5.13Patrick Steinhardt1-18/+14
When executing t9300 with Dash v0.5.13.1 we can see that the test hangs completely with the following (condensed) trace: git fast-import + error=1 + read output + cat input + echo checkpoint + echo progress checkpoint + test rogress checkpoint = progress checkpoint + test rogress checkpoint = UNEXPECTED + echo cruft: rogress checkpoint cruft: rogress checkpoint + read output + test = progress checkpoint + test = UNEXPECTED + echo cruft: cruft: + read output Basically, what's happening here is that we spawn git-fast-import(1) and wait for it to output a certain string, "progress checkpoint". Curiously though, what we end up reading is "rogress checkpoint" -- so the first byte of the expected string is missing. Same as in the preceding commit, this seems to be a bug in Dash itself that bisects to c5bf970 (expand: Add multi-byte support to pmatch, 2024-06-02). But other than in the preceding commit, this bug has already been fixed upstream in 079059a (input: Fix heap-buffer-overflow in preadbuffer on long lines, 2026-02-11), which is part of v0.5.13.2. For now though, work around the bug by waiting for the expected output in a different way. There is no good reason why one version should work better than the other, but at least the new version doesn't exhibit the bug. And, if you ask me, it's also slightly easier to read. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02t: work around multibyte bug in quoted heredocs with Dash v0.5.13Patrick Steinhardt6-18/+40
When executing our test suite with Dash v0.5.13.2 one can observe several test failures that all have the same symptoms: we have a quoted heredoc that contains multibyte characters, but the final data does not match what we actually wanted to write. One such example is in t0300, where we see the diffs like the following: --- expect-stdout 2026-04-01 07:25:45.249919440 +0000 +++ stdout 2026-04-01 07:25:45.254919509 +0000 @@ -1,5 +1,5 @@ protocol=https host=example.com -path=perú.git +path=perú.git username=foo password=bar While seemingly the same, the data that we've written via the heredoc contains some invisible bytes. The expected hex representation of the string is: 7065 72c3 ba2e 6769 74 per...git But what we actually get instead is this string: 7065 7285 02c3 ba02 852e 6769 74 per.......git What's important to note here is that the multibyte character exists in both versions. But in the broken version we see that the bytes are wrapped in a sequence of "85 02" and "02 85". This is the CTLMBCHAR byte sequence of Dash, which it uses internally to quote multibyte sequences. As it turns out, this bug was introduced in c5bf970 (expand: Add multi-byte support to pmatch, 2024-06-02), which adds multibyte support to more contexts of Dash. One of these contexts seems to be in heredocs, and Dash _does_ correctly unquote these multibyte sequences when using an unquoted heredoc. But the bug seems to be that this unquoting does not happen in quoted heredocs, and the bug still exists on the latest "master" branch. For now, work around the bug by using unquoted heredocs instead. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02reftable/system: add abstraction to mmap filesPatrick Steinhardt3-12/+45
In our codebase we have a couple of wrappers around mmap(3p) that allow us to reimplement the syscall on platforms that don't have it natively, like for example Windows. Other projects that embed the reftable library may have a different infra though to hook up mmap wrappers, but these are currently hard to integrate. Provide the infrastructure to let projects easily define the mmap interface with a custom struct and custom functions. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02reftable/system: add abstraction to retrieve time in millisecondsPatrick Steinhardt3-23/+13
We directly call gettimeofday(3p), which may not be available on some platforms. Provide the infrastructure to let projects easily use their own implementations of this function. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02reftable/fsck: use REFTABLE_UNUSED instead of UNUSEDPatrick Steinhardt1-1/+1
While we have the reftable-specific `REFTABLE_UNUSED` header, we accidentally introduced a new usage of the Git-specific `UNUSED` header into the reftable library in 9051638519 (reftable: add code to facilitate consistency checks, 2025-10-07). Convert the site to use `REFTABLE_UNUSED`. Ideally, we'd move the definition of `UNUSED` into "git-compat-util.h" so that it becomes in accessible to the reftable library. But this is unfortunately not easily possible as "compat/mingw-posix.h" requires this macro, and this header is included by "compat/posix.h". Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02reftable/stack: provide fsync(3p) via system headerPatrick Steinhardt5-22/+12
Users of the reftable library are expected to provide their own function callback in cases they want to sync(3p) data to disk via the reftable write options. But if no such function was provided we end up calling fsync(3p) directly, which may not even be available on some systems. While dropping the explicit call to fsync(3p) would work, it would lead to an unsafe default behaviour where a project may have forgotten to set up the callback function, and that could lead to potential data loss. So this is not a great solution. Instead, drop the callback function and make it mandatory for the project to define fsync(3p). In the case of Git, we can then easily inject our custom implementation via the "reftable-system.h" header so that we continue to use `fsync_component()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-02reftable: introduce "reftable-system.h" headerPatrick Steinhardt13-12/+34
We're including a couple of standard headers like <stdint.h> in a bunch of locations, which makes it hard for a project to plug in their own logic for making required functionality available. For us this is for example via "compat/posix.h", which already includes all of the system headers relevant to us. Introduce a new "reftable-system.h" header that allows projects to provide their own headers. This new header is supposed to contain all the project-specific bits to provide the POSIX-like environment, and some additional supporting code. With this change, we thus have the following split in our system-specific code: - "reftable/reftable-system.h" is the project-specific header that provides a POSIX-like environment. Every project is expected to provide their own implementation. - "reftable/system.h" contains the project-independent definition of the interfaces that a project needs to implement. This file should not be touched by a project. - "reftable/system.c" contains the project-specific implementation of the interfaces defined in "system.h". Again, every project is expected to provide their own implementation. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-01refs/files-backend: drop const to fix strchr() warningJeff King3-6/+8
In show_one_reflog_ent(), we're fed a writable strbuf buffer, which we parse into the various reflog components. We write a NUL over email_end to tie off one of the fields, and thus email_end must be non-const. But with a C23 implementation of libc, strchr() will now complain when assigning the result to a non-const pointer from a const one. So we can fix this by making the source pointer non-const. But there's a catch. We derive that source pointer by parsing the line with parse_oid_hex_algop(), which requires a const pointer for its out-parameter. We can work around that by teaching it to use our CONST_OUTPARAM() trick, just like skip_prefix(). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-01http: drop const to fix strstr() warningJeff King2-4/+6
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>
2026-04-01range-diff: drop const to fix strstr() warningsJeff King1-1/+1
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>
2026-04-01pkt-line: make packet_reader.line non-constJeff King3-7/+9
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>
2026-04-01skip_prefix(): check const match between in and out paramsJeff King1-2/+19
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: char *in = ...; char *out; if (skip_prefix(in, "foo", &out)) *out = '\0'; 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: const char *in = ...; char *out; if (skip_prefix(in, "foo", (const char **)&out)) *out = '\0'; 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: int foo(const char *x, const char **y); #define foo(in,out) foo((in), CONST_OUTPARAM((in), (out))) void ok_const(const char *x, const char **y) { foo(x, y); } void ok_nonconst(char *x, char **y) { foo(x, y); } void ok_add_const(char *x, const char **y) { foo(x, y); } void bad_drop_const(const char *x, char **y) { foo(x, y); } gcc reports: 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>
2026-04-01pseudo-merge: fix disk reads from find_pseudo_merge()Jeff King1-13/+19
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>
2026-04-01find_last_dir_sep(): convert inline function to macroJeff King1-5/+1
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>
2026-04-01run-command: explicitly cast away constness when assigning to voidJeff King1-2/+2
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>
2026-04-01pager: explicitly cast away strchr() constnessJeff King1-2/+3
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>
2026-04-01transport-helper: drop const to fix strchr() warningsJeff King1-1/+2
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>
2026-04-01http: add const to fix strchr() warningsJeff King1-1/+1
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>
2026-04-01convert: add const to fix strchr() warningsJeff King1-1/+2
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>
2026-04-01replay: allow to specify a ref with option --refToon Claes5-10/+128
When option '--onto' is passed to git-replay(1), the command will update refs from the <revision-range> passed to the command. When using option '--advance' or '--revert', the argument of that option is a ref that will be updated. To enable users to specify which ref to update, add option '--ref'. When using option '--ref', the refs described above are left untouched and instead the argument of this option is updated instead. Because this introduces code paths in replay.c that jump to `out` before init_basic_merge_options() is called on `merge_opt`, zero-initialize the struct. Signed-off-by: Toon Claes <toon@iotcl.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-01replay: use stuck form in documentation and help messageToon Claes2-14/+15
gitcli(7) suggests to use stuck form. Change the documentation strings to use this form. While at it, reorder them to match the order in the docs. Signed-off-by: Toon Claes <toon@iotcl.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-01builtin/replay: mark options as not negatableToon Claes1-12/+16
The options '--onto', '--advance', '--revert', and '--ref-action' of git-replay(1) are not negatable. Mark them as such using PARSE_OPT_NONEG. Signed-off-by: Toon Claes <toon@iotcl.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-01Git 2.54-rc0v2.54.0-rc0Junio C Hamano1-1/+1
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-04-01RelNotes: minor typo fixes in 2.54.0 draftTodd Zullinger1-2/+2
Signed-off-by: Todd Zullinger <tmz@pobox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>