]> git.ipfire.org Git - thirdparty/git.git/log
thirdparty/git.git
7 weeks agot7004: avoid subshells to capture git exit codes
Siddharth Shrimali [Tue, 21 Apr 2026 05:33:34 +0000 (11:03 +0530)] 
t7004: avoid subshells to capture git exit codes

Several tests in t7004 use the 'test$(git ...) = ...' or the '! (git ...)'
subshell pattern. This swallows git's exit code. If git crashes
(e.g. segmentation fault) the crash would go undetected, and the test
would fail due to a mismatch or an inverted exit code.

Modernize these tests by directly writing output to files(actual) and
verifying them with 'test_cmp' or 'test_grep'. Replace subshell
negations with 'test_must_fail'. This way, if git crashes, the test
fails immediately and clearly instead of hiding the error behind a
string mismatch.

Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 weeks agot7004: dynamically grab expected state in tests
Siddharth Shrimali [Tue, 21 Apr 2026 05:33:33 +0000 (11:03 +0530)] 
t7004: dynamically grab expected state in tests

The tests for 'Multiple -l or --list options' and 'trying to delete
tags without params', hardcodes that exactly one or two specific tags
('myhead', 'mytag') exist in the repository.

If other tests are added, modified, or removed earlier in the script,
this expected global state will change, resulting in these tests to fail
for completely unrelated reasons.

Instead of hardcoding the expected tags, dynamically grab the state
of the repository before running the commands under test ('git tag -l'
and 'git tag -d'), and verify that the output matches or remains
unchanged afterward. This keeps the tests independent from the script's
overall state.

Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
7 weeks agot7004: drop hardcoded tag count for state verification
Siddharth Shrimali [Tue, 21 Apr 2026 05:33:32 +0000 (11:03 +0530)] 
t7004: drop hardcoded tag count for state verification

The test 'trying to create a tag with a non-valid name should fail',
checked that exactly one tag existed in the repository before and after
attempting to create invalid tags.

As pointed out by Junio, this makes the test brittle by relying on a
specific global tag count. If future tests are added or removed before
this test, the expected state changes and this test would break for
completely unrelated reasons.

Modernize the test by taking a snapshot of the existing tags before the
failure attempts and comparing it to a snapshot taken after.
This provides a "belt-and-suspenders" approach: we verify that
'git tag' both exits with the expected error code and leaves the
repository state untouched, without being brittle to the specific
number of tags present.

This replaces the hardcoded 'test_line_count = 1' checks with 'test_cmp'
to ensure the tag list remains identical.

Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agodiff: fix out-of-bounds reads and NULL deref in diffstat UTF-8 truncation
Elijah Newren [Mon, 20 Apr 2026 15:42:58 +0000 (15:42 +0000)] 
diff: fix out-of-bounds reads and NULL deref in diffstat UTF-8 truncation

f85b49f3d4a (diff: improve scaling of filenames in diffstat to handle
UTF-8 chars, 2026-01-16) introduced a loop in show_stats() that calls
utf8_width() repeatedly to skip leading characters until the displayed
width fits.  However, utf8_width() can return problematic values:

  - For invalid UTF-8 sequences, pick_one_utf8_char() sets the name
    pointer to NULL and utf8_width() returns 0.  Since name_len does
    not change, the loop iterates once more and pick_one_utf8_char()
    dereferences the NULL pointer, crashing.

  - For control characters, utf8_width() returns -1, so name_len
    grows when it is expected to shrink.  This can cause the loop to
    consume more characters than the string contains, reading past
    the trailing NUL.

By default, fill_print_name() will C-quote filenames which escapes
control characters and invalid bytes to printable text.  That avoids
this bug from being triggered; however, with core.quotePath=false,
most characters are no longer escaped (though some control characters
still are) and raw bytes can reach this code.

Add tests exercising both failure modes with core.quotePath=false and
a narrow --stat-name-width to force truncation: one with a bare 0xC0
byte (invalid UTF-8 lead byte, triggers NULL deref) and one with
several C1 control characters (repeats of 0xC2 0x9F, causing
the loop to read past the end of the string).  The second test
reliably catches the out-of-bounds read when run under ASan, though
it may pass silently without sanitizers.

Fix both issues by introducing utf8_ish_width(), a thin wrapper
around utf8_width() that guarantees the pointer always advances and
the returned width is never negative:

  - On invalid UTF-8 it restores the pointer, advances by one byte,
    and returns width 1 (matching the strlen()-based fallback used
    by utf8_strwidth()).
  - On a control character it returns 0 (matching utf8_strnwidth()
    which skips them).

Also add a "&& *name" guard to the while-loop condition so it
terminates at end-of-string even when utf8_strwidth()'s strlen()
fallback causes name_len to exceed the sum of per-character widths.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agoGit 2.54 v2.54.0
Junio C Hamano [Mon, 20 Apr 2026 02:01:39 +0000 (19:01 -0700)] 
Git 2.54

Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agoMerge tag 'l10n-2.54.0-v2' of https://github.com/git-l10n/git-po
Junio C Hamano [Mon, 20 Apr 2026 01:59:09 +0000 (18:59 -0700)] 
Merge tag 'l10n-2.54.0-v2' of https://github.com/git-l10n/git-po

l10n-2.54.0-v2

* tag 'l10n-2.54.0-v2' of https://github.com/git-l10n/git-po:
  l10n: bg.po: Updated Bulgarian translation (6226t)
  l10n: zh_TW: update translation for Git 2.54
  l10n: Update Catalan Translation
  l10n: ga.po: update for Git 2.54
  l10n: fr: v2.54.0
  l10n: tr: Update Turkish translations
  l10n: sv.po: Update Swedish translation
  l10n: sv.po: correct various translations
  l10n: zh_CN: updated translation for 2.54
  l10n: bg.po: Updated Bulgarian translation (6226t)
  l10n: zh_CN: post-2.53 code review
  l10n: document AI and PO helper in po/README
  l10n: docs: add review instructions in AGENTS.md
  l10n: docs: add translation instructions in AGENTS.md
  l10n: docs: add update PO instructions in AGENTS.md
  l10n: docs: add AGENTS.md with update POT instructions
  l10n: add .gitattributes to simplify location filtering
  l10n: fix 'zh_TW.po' 'Applying patch'

8 weeks agoMerge branch 'master' of github.com:alshopov/git-po
Jiang Xin [Sun, 19 Apr 2026 23:37:21 +0000 (07:37 +0800)] 
Merge branch 'master' of github.com:alshopov/git-po

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

8 weeks agol10n: bg.po: Updated Bulgarian translation (6226t)
Alexander Shopov [Sun, 19 Apr 2026 14:07:40 +0000 (16:07 +0200)] 
l10n: bg.po: Updated Bulgarian translation (6226t)

Improvements prompted by AI-assisted review

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
8 weeks agol10n: zh_TW: update translation for Git 2.54
Yi-Jyun Pan [Sun, 19 Apr 2026 13:52:38 +0000 (21:52 +0800)] 
l10n: zh_TW: update translation for Git 2.54

Signed-off-by: Yi-Jyun Pan <pan93412@gmail.com>
8 weeks agoMerge branch 'fr_v2.54.0' of github.com:jnavila/git
Jiang Xin [Sun, 19 Apr 2026 10:41:17 +0000 (18:41 +0800)] 
Merge branch 'fr_v2.54.0' of github.com:jnavila/git

* 'fr_v2.54.0' of github.com:jnavila/git:
  l10n: fr: v2.54.0

8 weeks agoMerge branch 'master' of github.com:alshopov/git-po
Jiang Xin [Sun, 19 Apr 2026 10:26:22 +0000 (18:26 +0800)] 
Merge branch 'master' of github.com:alshopov/git-po

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

8 weeks agol10n: Update Catalan Translation
Mikel Forcada [Fri, 10 Apr 2026 19:55:34 +0000 (21:55 +0200)] 
l10n: Update Catalan Translation

Signed-off-by: Mikel Forcada <mikel.forcada@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
8 weeks agol10n: ga.po: update for Git 2.54
Aindriú Mac Giolla Eoin [Thu, 9 Apr 2026 14:50:17 +0000 (15:50 +0100)] 
l10n: ga.po: update for Git 2.54

Signed-off-by: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>
8 weeks agoMerge branch 'master' of github.com:nafmo/git-l10n-sv
Jiang Xin [Sun, 19 Apr 2026 08:54:14 +0000 (16:54 +0800)] 
Merge branch 'master' of github.com:nafmo/git-l10n-sv

* 'master' of github.com:nafmo/git-l10n-sv:
  l10n: sv.po: Update Swedish translation
  l10n: sv.po: correct various translations

8 weeks agoMerge branch 'apply-patch-reject' of github.com:A4-Tacks/git-po
Jiang Xin [Sun, 19 Apr 2026 08:50:58 +0000 (16:50 +0800)] 
Merge branch 'apply-patch-reject' of github.com:A4-Tacks/git-po

* 'apply-patch-reject' of github.com:A4-Tacks/git-po:
  l10n: fix 'zh_TW.po' 'Applying patch'

8 weeks agoMerge branch 'tr-l10n' of github.com:bitigchi/git-po
Jiang Xin [Sun, 19 Apr 2026 03:13:45 +0000 (11:13 +0800)] 
Merge branch 'tr-l10n' of github.com:bitigchi/git-po

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

8 weeks agoMerge branch 'zh_CN-2.54' of github.com:jiangxin/git
Jiang Xin [Sun, 19 Apr 2026 03:01:51 +0000 (11:01 +0800)] 
Merge branch 'zh_CN-2.54' of github.com:jiangxin/git

* 'zh_CN-2.54' of github.com:jiangxin/git:
  l10n: zh_CN: updated translation for 2.54

8 weeks agogitk: add horizontal scrollbar to the commit list pane
Rob McDonald [Tue, 14 Apr 2026 16:34:03 +0000 (09:34 -0700)] 
gitk: add horizontal scrollbar to the commit list pane

When many branches and tags decorate the same commit, the ref labels
push the commit description far to the right, often out of the visible
area of the left pane.  The canvas widget already tracked the maximum
x extent via canvxmax and updated its scrollregion accordingly, but
there was no scrollbar wired up to let the user reach that content.

Add a horizontal scrollbar (.tf.histframe.cxsb) below the three-pane
history area, connected to the left canvas (canv) via its xscrollcommand
and xview.

No behaviour is changed for the author (canv2) or date (canv3) panes;
they continue to scroll only vertically in lock-step as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Rob McDonald <rob.a.mcdonald@gmail.com>
8 weeks agol10n: fr: v2.54.0
Jean-Noël Avila [Sat, 18 Apr 2026 04:05:05 +0000 (12:05 +0800)] 
l10n: fr: v2.54.0

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
8 weeks agoCodingGuidelines: st_mtimespec vs st_mtim vs st_mtime
Junio C Hamano [Fri, 10 Apr 2026 18:10:48 +0000 (11:10 -0700)] 
CodingGuidelines: st_mtimespec vs st_mtim vs st_mtime

Most unfortunately macOS does not support st_[amc]tim for timestamps
down to nanosecond resolution as POSIX systems.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agodoc: fix grammar errors in submodule description
Elijah Newren [Thu, 16 Apr 2026 23:36:31 +0000 (23:36 +0000)] 
doc: fix grammar errors in submodule description

6cc6d1b4c699 (Documentation: update add --force option + ignore=all
config, 2026-02-06) added text describing both the ignore=none and
ignore=all behaviors.  The former had minor formatting and grammatical
errors, while the latter was a bit garbled.  I have tried to tweak the
wording on the latter to make it read as I think was intended, and fixed
the minor grammatical issues with both as well.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agodoc: fix singular/plural mismatch in git-rerere
Elijah Newren [Thu, 16 Apr 2026 23:36:30 +0000 (23:36 +0000)] 
doc: fix singular/plural mismatch in git-rerere

conflict -> conflicts

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agodoc: fix plural agreement in pack.preferBitmapTips
Elijah Newren [Thu, 16 Apr 2026 23:36:29 +0000 (23:36 +0000)] 
doc: fix plural agreement in pack.preferBitmapTips

hierarchies -> hierarchy

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agodoc: fix self-referential config in sendemail.smtpSSLClientKey
Elijah Newren [Thu, 16 Apr 2026 23:36:28 +0000 (23:36 +0000)] 
doc: fix self-referential config in sendemail.smtpSSLClientKey

a8215a205141 (send-email: add client certificate options, 2026-03-02)
added documentation for sendemail.smtpSSLClientKey that says it works
"in conjunction with `sendemail.smtpSSLClientKey`" -- referring to
itself.  It appears that `sendemail.smtpSSLClientCert` was the intended
reference; fix it.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agoCodingGuidelines: fix subject-verb agreement
Elijah Newren [Thu, 16 Apr 2026 23:36:27 +0000 (23:36 +0000)] 
CodingGuidelines: fix subject-verb agreement

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agoRelNotes/2.54.0: fix typos and grammar
Elijah Newren [Thu, 16 Apr 2026 23:36:26 +0000 (23:36 +0000)] 
RelNotes/2.54.0: fix typos and grammar

Fix various issues in the release notes -- missing/wrong articles, typo,
indentation, quote consistency, and wording improvement or corrections.

Other than the indentation fix for "The way combined list-object filter
options...", this patch is much easier to view with --color-words.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agol10n: tr: Update Turkish translations
Emir SARI [Sat, 4 Apr 2026 19:09:05 +0000 (22:09 +0300)] 
l10n: tr: Update Turkish translations

Signed-off-by: Emir SARI <emir_sari@icloud.com>
8 weeks agoMerge branch 'jk/midx-write-v1-by-default'
Junio C Hamano [Thu, 16 Apr 2026 22:43:26 +0000 (15:43 -0700)] 
Merge branch 'jk/midx-write-v1-by-default'

As writing version 2 MIDX files by default breaks older versions of
Git and its reimplementations, use V2 only when necessary.

* jk/midx-write-v1-by-default:
  MIDX: revert the default version to v1

8 weeks agoMIDX: revert the default version to v1
Jeff King [Thu, 16 Apr 2026 20:06:59 +0000 (16:06 -0400)] 
MIDX: revert the default version to v1

We introduced midx version 2 in b2ec8e90c2 (midx: do not require packs
to be sorted in lexicographic order, 2026-02-24) and now write it by
default. The rationale was that older versions should ignore the v2 midx
and fall back to using the packs (just like we do for other midx
errors). Unfortunately this is not the case, as we have a hard die()
when we see an unknown midx version.

As a result, writing a midx with Git 2.54-rc2 puts the repository into a
state that is unusable with Git 2.53. And this midx write may happen
behind the scenes as part of normal operations, like fetch.

Let's switch back to writing v1 by default to avoid regressing the case
where multiple versions of Git are used on the same repository.

There is one gotcha, though: the v2 format is required for some new
features, like midx compaction, and running "git multi-pack-index
compact" will complain when asked to write a v1 index. The user must set
midx.version to "2" to make the feature work.

So instead of always using v1, we'll base the default on whether the
requested feature requires v2. That does mean that running midx
compaction will create a repository that can't be read by older versions
of Git. But we never do that by default; only people experimenting with
the new feature will be affected.

We have to adjust the test expectation in t5319, since it will now
generate v1 files. And our "auto-select v2" is covered by the tests in
t5335, which continue to check that compaction works without having to
set midx.version manually (and also explicitly check that asking for v1
with compaction reports the problem).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agot5563: add tests for http.emptyAuth with Negotiate
Matthew John Cheetham [Thu, 16 Apr 2026 09:20:59 +0000 (09:20 +0000)] 
t5563: add tests for http.emptyAuth with Negotiate

Add tests exercising the interaction between http.emptyAuth and
servers that advertise Negotiate (SPNEGO) authentication.

Verify that auto mode gives Negotiate a chance via empty auth
(resulting in two 401 responses before falling through to
credential_fill with Basic credentials), and that false mode
strips Negotiate immediately (only one 401 response).

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agohttp: attempt Negotiate auth in http.emptyAuth=auto mode
Matthew John Cheetham [Thu, 16 Apr 2026 09:20:58 +0000 (09:20 +0000)] 
http: attempt Negotiate auth in http.emptyAuth=auto mode

When a server advertises Negotiate (SPNEGO) authentication, the
"auto" mode of http.emptyAuth should detect this as an "exotic"
method and proactively send empty credentials, allowing libcurl to
use the system Kerberos ticket without prompting the user.

However, two features interact to prevent this from working:

The Negotiate-stripping logic, introduced in 4dbe66464b
(remote-curl: fall back to Basic auth if Negotiate fails,
2015-01-08), removes CURLAUTH_GSSNEGOTIATE from the allowed
methods on the first 401 response. The empty-auth auto-detection,
introduced in 40a18fc77c (http: add an "auto" mode for
http.emptyauth, 2017-02-25), then checks the remaining methods
for anything "exotic" -- but Negotiate has already been removed,
so auto mode never activates for servers whose only non-Basic/Digest
method is Negotiate (e.g., Apache with mod_auth_kerb offering
Basic + Negotiate).

Fix this by delaying the Negotiate stripping in auto mode: on the
first 401, keep Negotiate in the allowed methods so that auto mode
can detect it and retry with empty credentials. If that attempt
fails (no valid Kerberos ticket), strip Negotiate on the second 401
and fall through to credential_fill() as usual.

To support this, also teach http_reauth_prepare() to skip
credential_fill() when empty auth is about to be attempted, since
filling real credentials would bypass the empty-auth mechanism.

The true and false modes are unchanged: true sends empty credentials
on the very first request (before any 401), and false never sends
them.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agohttp: extract http_reauth_prepare() from retry paths
Matthew John Cheetham [Thu, 16 Apr 2026 09:20:57 +0000 (09:20 +0000)] 
http: extract http_reauth_prepare() from retry paths

All three HTTP retry paths (http_request_recoverable, post_rpc,
probe_rpc) call credential_fill() directly when handling
HTTP_REAUTH. Extract this into a helper function so that a
subsequent commit can add pre-fill logic (such as attempting
empty-auth before prompting) in one place.

No functional change.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
8 weeks agol10n: sv.po: Update Swedish translation
Peter Krefting [Thu, 16 Apr 2026 11:30:54 +0000 (12:30 +0100)] 
l10n: sv.po: Update Swedish translation

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
8 weeks agol10n: sv.po: correct various translations
Stefan Björnelund [Fri, 13 Feb 2026 20:14:23 +0000 (21:14 +0100)] 
l10n: sv.po: correct various translations

- correct translation of pathspec msgs
  Corrects cases where the “pathspec” is translated as if it was a
  path
- correct translation of refspec msgs
  Corrects cases where the “refspec” were not consistently translated
- correct translation of credential msgs
  Corrects cases where the “credential” were not correctly translated

Signed-off-by: Stefan Björnelund <stefan.bjornelund.gnome@gmail.com>
Modified-by: Peter Krefting <peter@softwolves.pp.se>
2 months agocat-file: add mailmap subcommand to --batch-command
Siddharth Asthana [Thu, 16 Apr 2026 03:32:50 +0000 (09:02 +0530)] 
cat-file: add mailmap subcommand to --batch-command

git-cat-file(1)'s --batch-command works with the --use-mailmap option,
but this option needs to be set when the process is created. This means
we cannot change this option mid-operation.

At GitLab, Gitaly keeps interacting with a long-lived git-cat-file
process and it would be useful if --batch-command supported toggling
mailmap dynamically on an existing process.

Add a `mailmap` subcommand to --batch-command that takes a boolean
argument (usual ways you can specify a boolean value like 'yes', 'true',
etc., are supported). Mailmap data is loaded lazily and kept in memory,
while a helper centralizes the one-time load path used both at startup
and from the batch-command handler.

Extend tests to cover runtime toggling, startup option interactions
(`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.

Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agol10n: zh_CN: updated translation for 2.54
Jiang Xin [Tue, 31 Mar 2026 02:17:35 +0000 (10:17 +0800)] 
l10n: zh_CN: updated translation for 2.54

Translate 198 previously fuzzy or untranslated messages, bringing the
total number of translated messages to 6226.

Reviewed-by: 依云 <lilydjwg@gmail.com>
Reviewed-by: Fangyi Zhou <me@fangyi.io>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2 months agobackfill: default to grabbing edge blobs too
Elijah Newren [Wed, 15 Apr 2026 23:58:02 +0000 (23:58 +0000)] 
backfill: default to grabbing edge blobs too

Commit 302aff09223f (backfill: accept revision arguments, 2026-03-26) added
support for accepting revision arguments to backfill.  This allows users
to do things like

   git backfill --remotes ^v2.3.0

and then run many commands without triggering on-demand downloads of
blobs.  However, if they have topics based on v2.3.0, they will likely
still trigger on-demand downloads.  Consider, for example, the command

   git log -p v2.3.0..topic

This would still trigger on-demand blob loadings after the backfill
command above, because the commit(s) with A as a parent will need to
diff against the blobs in A.  In fact, multiple commands need blobs from
the lower boundary of the revision range:

   * git log -p A..B                # After backfill A..B
   * git replay --onto TARGET A..B  # After backfill TARGET^! A..B
   * git checkout A && git merge B  # After backfill A...B

Add an extra --[no-]include-edges flag to allow grabbing blobs from
edge commits.  Since the point of backfill is to prevent on-demand blob
loading and these are common commands, default to --include-edges.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agobackfill: document acceptance of revision-range in more standard manner
Elijah Newren [Wed, 15 Apr 2026 23:58:01 +0000 (23:58 +0000)] 
backfill: document acceptance of revision-range in more standard manner

302aff09223f (backfill: accept revision arguments, 2026-03-26) added
support for passing revision arguments to 'git backfill' but documented
them only with a prose sentence:

    You may also specify the commit limiting options from
    git-rev-list(1).

No other command that accepts revision arguments documents them this
way.  Commands like log, shortlog, and replay define a formal
<revision-range> entry and include rev-list-options.adoc.  Commands like
bundle, fast-export, and filter-branch, which pass arguments through to
the revision machinery without including the full options file, still
define a formal <git-rev-list-args> entry explaining what is accepted.

Add a formal <revision-range> entry in the synopsis and OPTIONS section,
following the convention used by other commands, and mention that
commit-limiting options from git-rev-list(1) are also accepted.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agobackfill: reject rev-list arguments that do not make sense
Elijah Newren [Wed, 15 Apr 2026 23:58:00 +0000 (23:58 +0000)] 
backfill: reject rev-list arguments that do not make sense

Some rev-list options accepted by setup_revisions() are silently
ignored or actively counterproductive when used with 'git backfill',
because the path-walk API has its own tree-walking logic that bypasses
the mechanisms these options rely on:

  * -S/-G (pickaxe) and --diff-filter work by computing per-commit
    diffs in get_revision_1() and filtering commits whose diffs don't
    match.  Since backfill's goal is to download all blobs reachable
    from commits in the range, filtering out commits based on diff
    content would silently skip blobs -- the opposite of what users
    want.

  * --follow disables path pruning (revs->prune) and only makes
    sense for tracking a single file through renames in log output.
    It has no useful interaction with backfill.

  * -L (line-log) computes line-level diffs to track the evolution
    of a function or line range.  Like pickaxe, it filters commits
    based on diff content, which would cause blobs to be silently
    skipped.

  * --diff-merges controls how merge commit diffs are displayed.
    The path-walk API walks trees directly and never computes
    per-commit diffs, so this option would be silently ignored.

  * --filter (object filtering, e.g. --filter=blob:none) is used by
    the list-objects traversal but is completely ignored by the
    path-walk API, so it would silently do nothing.

Rather than letting users think these options are being honored,
reject them with a clear error message.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agocodeql: bump actions/cache from 4 to 5
Johannes Schindelin [Mon, 13 Apr 2026 16:24:17 +0000 (16:24 +0000)] 
codeql: bump actions/cache from 4 to 5

Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major

Originally-authored-by: dependabot[bot] <support@github.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agol10n: bg.po: Updated Bulgarian translation (6226t)
Alexander Shopov [Tue, 7 Apr 2026 07:32:08 +0000 (09:32 +0200)] 
l10n: bg.po: Updated Bulgarian translation (6226t)

Signed-off-by: Alexander Shopov <ash@kambanaria.org>
2 months agofsmonitor: convert shown khash to strset in do_handle_client
Paul Tarjan [Wed, 15 Apr 2026 13:27:37 +0000 (13:27 +0000)] 
fsmonitor: convert shown khash to strset in do_handle_client

Replace the khash-based string set used for deduplicating pathnames
in do_handle_client() with a strset, which provides a cleaner
interface for the same purpose.

Since the paths are interned strings from the batch data, use
strdup_strings=0 to avoid unnecessary copies.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: add tests for Linux
Paul Tarjan [Wed, 15 Apr 2026 13:27:36 +0000 (13:27 +0000)] 
fsmonitor: add tests for Linux

Add a smoke test that verifies the filesystem actually delivers
inotify events to the daemon.  On some configurations (e.g.,
overlayfs with older kernels), inotify watches succeed but events
are never delivered.  The daemon cookie wait will time out, but
every subsequent test would fail.  Skip the entire test file early
when this is detected.

Add a test that exercises rapid nested directory creation to verify
the daemon correctly handles the EEXIST race between recursive scan
and queued inotify events.  When IN_MASK_CREATE is available and a
directory watch is added during recursive registration, the kernel
may also deliver a queued IN_CREATE event for the same directory.
The second inotify_add_watch() returns EEXIST, which must be treated
as harmless.  An earlier version of the listener crashed in this
scenario.

Reduce --start-timeout from the default 60 seconds to 10 seconds so
that tests fail promptly when the daemon cannot start.

Harden the test helpers to work in environments without procps
(e.g., Fedora CI): fall back to reading /proc/$pid/stat for the
process group ID when ps is unavailable, guard stop_git() against
an empty pgid, and redirect stderr from kill to /dev/null to avoid
noise when processes have already exited.

Use set -m to enable job control in the submodule-pull test so that
the background git pull gets its own process group, preventing the
shell wait from blocking on the daemon.  setsid() in the previous
commit detaches the daemon itself, but the intermediate git pull
process still needs its own process group for the test shell to
manage it correctly.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: add timeout to daemon stop command
Paul Tarjan [Wed, 15 Apr 2026 13:27:35 +0000 (13:27 +0000)] 
fsmonitor: add timeout to daemon stop command

The "fsmonitor--daemon stop" command polls in a loop waiting for the
daemon to exit after sending a "quit" command over IPC.  If the daemon
fails to shut down (e.g. it is stuck or wedged), this loop spins
forever.

Add a 30-second timeout so the stop command returns an error instead
of blocking indefinitely.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: close inherited file descriptors and detach in daemon
Paul Tarjan [Wed, 15 Apr 2026 13:27:34 +0000 (13:27 +0000)] 
fsmonitor: close inherited file descriptors and detach in daemon

When the fsmonitor daemon is spawned as a background process, it may
inherit file descriptors from its parent that it does not need.  In
particular, when the test harness or a CI system captures output through
pipes, the daemon can inherit duplicated pipe endpoints.  If the daemon
holds these open, the parent process never sees EOF and may appear to
hang.

Set close_fd_above_stderr on the child process at both daemon startup
paths: the explicit "fsmonitor--daemon start" command and the implicit
spawn triggered by fsmonitor-ipc when a client finds no running daemon.
Also suppress stdout and stderr on the implicit spawn path to prevent
the background daemon from writing to the client's terminal.

Additionally, call setsid() when the daemon starts with --detach to
create a new session and process group.  This prevents the daemon
from being part of the spawning shell's process group, which could
cause the shell's "wait" to block until the daemon exits.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agorun-command: add close_fd_above_stderr option
Paul Tarjan [Wed, 15 Apr 2026 13:27:33 +0000 (13:27 +0000)] 
run-command: add close_fd_above_stderr option

Add a close_fd_above_stderr flag to struct child_process.  When set,
the child closes file descriptors 3 and above between fork and exec
(skipping the child-notifier pipe), capped at sysconf(_SC_OPEN_MAX)
or 4096, whichever is smaller.  This prevents the child from
inheriting pipe endpoints or other descriptors from the parent
environment (e.g., the test harness).

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: implement filesystem change listener for Linux
Paul Tarjan [Wed, 15 Apr 2026 13:27:32 +0000 (13:27 +0000)] 
fsmonitor: implement filesystem change listener for Linux

Implement the built-in fsmonitor daemon for Linux using the inotify
API, bringing it to feature parity with the existing Windows and macOS
implementations.

The implementation uses inotify rather than fanotify because fanotify
requires either CAP_SYS_ADMIN or CAP_PERFMON capabilities, making it
unsuitable for an unprivileged user-space daemon.  While inotify has
the limitation of requiring a separate watch on every directory (unlike
macOS's FSEvents, which can monitor an entire directory tree with a
single watch), it operates without elevated privileges and provides
the per-file event granularity needed for fsmonitor.

The listener uses inotify_init1(O_NONBLOCK) with a poll loop that
checks for events with a 50-millisecond timeout, keeping the inotify
queue well-drained to minimize the risk of overflows.  Bidirectional
hashmaps map between watch descriptors and directory paths for efficient
event resolution.  Directory renames are tracked using inotify's cookie
mechanism to correlate IN_MOVED_FROM and IN_MOVED_TO event pairs; a
periodic check detects stale renames where the matching IN_MOVED_TO
never arrived, forcing a resync.

New directory creation triggers recursive watch registration to ensure
all subdirectories are monitored.  The IN_MASK_CREATE flag is used
where available to prevent modifying existing watches, with a fallback
for older kernels.  When IN_MASK_CREATE is available and
inotify_add_watch returns EEXIST, it means another thread or recursive
scan has already registered the watch, so it is safe to ignore.

Remote filesystem detection uses statfs() to identify network-mounted
filesystems (NFS, CIFS, SMB, FUSE, etc.) via their magic numbers.
Mount point information is read from /proc/mounts and matched against
the statfs f_fsid to get accurate, human-readable filesystem type names
for logging.  When the .git directory is on a remote filesystem, the
IPC socket falls back to $HOME or a user-configured directory via the
fsmonitor.socketDir setting.

Based-on-patch-by: Eric DeCosta <edecosta@mathworks.com>
Based-on-patch-by: Marziyeh Esipreh <marziyeh.esipreh@gmail.com>
Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: rename fsm-settings-darwin.c to fsm-settings-unix.c
Paul Tarjan [Wed, 15 Apr 2026 13:27:31 +0000 (13:27 +0000)] 
fsmonitor: rename fsm-settings-darwin.c to fsm-settings-unix.c

The fsmonitor settings logic in fsm-settings-darwin.c is not
Darwin-specific and will be reused by the upcoming Linux
implementation.  Rename it to fsm-settings-unix.c to reflect that it
is shared by all Unix platforms.

Update the build files (meson.build and CMakeLists.txt) to use
FSMONITOR_OS_SETTINGS for fsm-settings, matching the approach already
used for fsm-ipc.

Based-on-patch-by: Eric DeCosta <edecosta@mathworks.com>
Based-on-patch-by: Marziyeh Esipreh <marziyeh.esipreh@gmail.com>
Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: rename fsm-ipc-darwin.c to fsm-ipc-unix.c
Paul Tarjan [Wed, 15 Apr 2026 13:27:30 +0000 (13:27 +0000)] 
fsmonitor: rename fsm-ipc-darwin.c to fsm-ipc-unix.c

The fsmonitor IPC path logic in fsm-ipc-darwin.c is not
Darwin-specific and will be reused by the upcoming Linux
implementation.  Rename it to fsm-ipc-unix.c to reflect that it
is shared by all Unix platforms.

Introduce FSMONITOR_OS_SETTINGS (set to "unix" for non-Windows, "win32"
for Windows) as a separate variable from FSMONITOR_DAEMON_BACKEND so
that the build files can distinguish between platform-specific files
(listen, health, path-utils) and shared Unix files (ipc, settings).

Move fsm-ipc to the FSMONITOR_OS_SETTINGS section in the Makefile, and
switch fsm-path-utils to use FSMONITOR_DAEMON_BACKEND since path-utils
is platform-specific (there will be separate darwin and linux versions).

Based-on-patch-by: Eric DeCosta <edecosta@mathworks.com>
Based-on-patch-by: Marziyeh Esipreh <marziyeh.esipreh@gmail.com>
Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: use pthread_cond_timedwait for cookie wait
Paul Tarjan [Wed, 15 Apr 2026 13:27:29 +0000 (13:27 +0000)] 
fsmonitor: use pthread_cond_timedwait for cookie wait

The cookie wait in with_lock__wait_for_cookie() uses an infinite
pthread_cond_wait() loop.  The existing comment notes the desire
to switch to pthread_cond_timedwait(), but the routine was not
available in git thread-utils.

On certain container or overlay filesystems, inotify watches may
succeed but events are never delivered.  In this case the daemon
would hang indefinitely waiting for the cookie event, which in
turn causes the client to hang.

Replace the infinite wait with a one-second timeout using
pthread_cond_timedwait().  If the timeout fires, report an
error and let the client proceed with a trivial (full-scan)
response rather than blocking forever.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agocompat/win32: add pthread_cond_timedwait
Paul Tarjan [Wed, 15 Apr 2026 13:27:28 +0000 (13:27 +0000)] 
compat/win32: add pthread_cond_timedwait

Add a pthread_cond_timedwait() implementation to the Windows pthread
compatibility layer using SleepConditionVariableCS() with a millisecond
timeout computed from the absolute deadline.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: fix hashmap memory leak in fsmonitor_run_daemon
Paul Tarjan [Wed, 15 Apr 2026 13:27:27 +0000 (13:27 +0000)] 
fsmonitor: fix hashmap memory leak in fsmonitor_run_daemon

The `state.cookies` hashmap is initialized during daemon startup but
never freed during cleanup in the `done:` label of
fsmonitor_run_daemon().  The cookie entries also have names allocated
via strbuf_detach() that must be freed individually.

Iterate the hashmap to free each cookie name, then call
hashmap_clear_and_free() to release the entries and table.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agofsmonitor: fix khash memory leak in do_handle_client
Paul Tarjan [Wed, 15 Apr 2026 13:27:26 +0000 (13:27 +0000)] 
fsmonitor: fix khash memory leak in do_handle_client

The `shown` kh_str_t was freed with kh_release_str() at a point in
the code only reachable in the non-trivial response path.  When the
client receives a trivial response, the code jumps to the `cleanup`
label, skipping the kh_release_str() call entirely and leaking the
hash table.

Fix this by initializing `shown` to NULL and moving the cleanup to the
`cleanup` label using kh_destroy_str(), which is safe to call on NULL.
This ensures the hash table is freed regardless of which code path is
taken.

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agot9210, t9211: disable GIT_TEST_SPLIT_INDEX for scalar clone tests
Paul Tarjan [Wed, 15 Apr 2026 13:27:25 +0000 (13:27 +0000)] 
t9210, t9211: disable GIT_TEST_SPLIT_INDEX for scalar clone tests

index.skipHash (Scalar default) and split-index are incompatible:
the shared index gets a null OID when skipHash skips computing the
hash, and the null OID causes the shared index to not be loaded on
re-read.  This triggers a BUG assertion in fsmonitor when the
fsmonitor_dirty bitmap references more entries than the (now empty)
index has.

Disable GIT_TEST_SPLIT_INDEX in the scalar clone tests that hit
this: tests 12, 13, and 22 in t9210 (matching the existing
workaround in test 16), and all of t9211 (every test does scalar
clone).

Signed-off-by: Paul Tarjan <github@paulisageek.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agouserdiff: extend Scheme support to cover other Lisp dialects
Scott L. Burson [Wed, 15 Apr 2026 02:27:43 +0000 (02:27 +0000)] 
userdiff: extend Scheme support to cover other Lisp dialects

Common Lisp has top-level forms, such as 'defun' and 'defmacro', that
are not matched by the current Scheme pattern.  Also, it is more
common in CL, when defining user macros intended as top-level forms,
to prefix their names with "def" instead of "define"; such forms are
also not matched.  And some top-level forms don't even begin with
"def".

On the other hand, it is an established formatting convention in the
Lisp community that only top-level forms start at the left margin.  So
matching any unindented line starting with an open parenthesis is an
acceptable heuristic; false positives will be rare.

However, there are also cases where notionally top-level forms are
grouped together within some containing form.  At least in the Common
Lisp community, it is conventional to indent these by two spaces, or
sometimes one.  But matching just an open parenthesis indented by two
spaces would be too broad; so the pattern added by this commit
requires an indented form to start with "(def".  It is believed that
this strikes a good balance between potential false positives and
false negatives.

Signed-off-by: Scott L. Burson <Scott@sympoiesis.com>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agouserdiff: tighten word-diff test case of the scheme driver
Johannes Sixt [Wed, 15 Apr 2026 02:27:42 +0000 (02:27 +0000)] 
userdiff: tighten word-diff test case of the scheme driver

The scheme driver separates identifiers only at parentheses of all
sorts and whitespace, except that vertical bars act as brackets that
enclose an identifier.

The test case attempts to demonstrate the vertical bars with a change
from 'some-text' to '|a greeting|'. However, this misses the goal
because the same word coloring would be applied if '|a greeting|'
were parsed as two words.

Have an identifier between vertical bars with a space in both the pre-
and the post-image and change only one side of the space to show that
the single word exists between the vertical bars.

Also add cases that change parentheses of all kinds in a sequence of
parentheses to show that they are their own word each.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Scott L. Burson <Scott@sympoiesis.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoGit 2.54-rc2 v2.54.0-rc2
Junio C Hamano [Tue, 14 Apr 2026 13:22:50 +0000 (06:22 -0700)] 
Git 2.54-rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoHopefully the final tweak before -rc2
Junio C Hamano [Mon, 13 Apr 2026 20:54:45 +0000 (13:54 -0700)] 
Hopefully the final tweak before -rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoMerge branch 'jc/ci-github-actions-use-checkout-v5'
Junio C Hamano [Mon, 13 Apr 2026 20:54:57 +0000 (13:54 -0700)] 
Merge branch 'jc/ci-github-actions-use-checkout-v5'

CI dependency updates.

* jc/ci-github-actions-use-checkout-v5:
  CI: bump actions/checkout from 4 to 5 for rust-analysis job

2 months agoMerge branch 'jk/doc-markup-sub-list-indentation'
Junio C Hamano [Mon, 13 Apr 2026 20:54:57 +0000 (13:54 -0700)] 
Merge branch 'jk/doc-markup-sub-list-indentation'

Doc mark-up update for entries in the glossary with bulleted lists.

* jk/doc-markup-sub-list-indentation:
  gitglossary: fix indentation of sub-lists

2 months agoMerge branch 'kh/doc-am-xref'
Junio C Hamano [Mon, 13 Apr 2026 20:54:57 +0000 (13:54 -0700)] 
Merge branch 'kh/doc-am-xref'

Doc update.

* kh/doc-am-xref:
  doc: am: correct to full --no-message-id
  doc: am: revert Message-ID trailer claim

2 months agogitglossary: fix indentation of sub-lists
Jeff King [Sat, 11 Apr 2026 21:55:18 +0000 (17:55 -0400)] 
gitglossary: fix indentation of sub-lists

The glossary entry is a list of terms and their definitions, so
multi-paragraph definitions need "+" continuation lines to indicate
that they are part of a single entry.

When an entry contains a sub-list (say, a bulleted list), the final "+"
may become ambiguous: is it connecting the next paragraph to the final
entry of the sub-list, or to the original list of definition paragraphs?

Asciidoc generally connects it to the former, even when we mean the
latter, and you end up with the next paragraph indented incorrectly,
like this:

  glob
    ...defines glob...

    Two consecutive asterisks ("**") in patterns matched
    against full pathname may have special meaning:

    - ...some special meaning of **...

    - ...another special meaning of **...

    - Other consecutive asterisks are considered invalid.

      Glob magic is incompatible with literal magic.

That final "Glob magic is incompatible" paragraph is in the wrong spot.
It should be at the same level as "Two consecutive asterisks", as it is
not part of the final "Other consecutive asterisks" bullet point.

The same problem appears in several other spots in the glossary.

Usually we'd fix this by using "--" markers, which put the sub-list into
its own block. But there's a catch: in some of these spots we are
already in an open block, and nesting open blocks is a problem. It seems
to work for me using Asciidoc 10.2.1, but Asciidoctor 2.0.26 makes a
mess of it (our intent to open a new block seems to close the old one).

Fortunately there's a work-around: when using a "+" list-continuation,
the number of empty lines above the continuation indicates which level
of parent list to continue. So by adding an empty line after our
unordered list (before the "+"), we should be able to continue the
definition list item.

But asciidoc being asciidoc, of course that is not the end of the story.
That technique works fine for the "glob" and "attr" lists in this patch,
but under the "refs" item it works for only 1 of the 2 lists! I can't
figure out why, and this may be an asciidoctor bug. But we can work
around it by using "--" open-block markers here, since we're not
already in an open block.

So using the extra blank line for the first two instances, and "--"
markers for the second two, this patch produces identical output from
"doc-diff HEAD^ HEAD" for both --asciidoctor and --asciidoc modes.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoCI: bump actions/checkout from 4 to 5 for rust-analysis job
Junio C Hamano [Mon, 13 Apr 2026 18:24:44 +0000 (11:24 -0700)] 
CI: bump actions/checkout from 4 to 5 for rust-analysis job

GitHub Actions started complaining about use of Node.js 20 and I was
wondering why only one job uses actions/checkout@v4, while everybody
else already uses actions/checkout@v5.

It turns out that it is caused by a semantic mismerge between
e75cd059 (ci: check formatting of our Rust code, 2025-10-15) that
added a new use of actions/checkout@v4 that happened very close to
another change 63541ed9 (build(deps): bump actions/checkout from 4
to 5, 2025-10-16) that updated all uses of actions/checkout@v4 to
use vactions/checkout@v5.

Update the leftover and the last use of actions/checkout@v4 to use
actions/checkout@v5 to help ourselves to move away from Node.js 20.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agodoc: am: correct to full --no-message-id
Kristoffer Haugsbakk [Sat, 11 Apr 2026 20:20:10 +0000 (22:20 +0200)] 
doc: am: correct to full --no-message-id

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agodoc: am: revert Message-ID trailer claim
Kristoffer Haugsbakk [Sat, 11 Apr 2026 20:15:50 +0000 (22:15 +0200)] 
doc: am: revert Message-ID trailer claim

I claimed in 3c18135b (doc: am: say that --message-id adds a trailer,
2026-02-09) that `git am --message-id` adds a Git trailer. But that
isn’t the case; for the case of a commit message with a subject, body,
and no trailer block:

    <subject>

    <paragrah>

It just appends the line right after `paragraph`:

    <subject>

    <paragraph>
    Message-ID: <message-id_trailer.323@msgid.xyz>

It does work for two other cases though, namely subject-only and with an
existing trailer block.

This is at best an inconsistency and arguably a bug, but we’re at the
trailing end of the release cycle now. So reverting the doc is safer
than making msg-id act as a trailer, for now.

Revert this hunk from commit 3c18135b except the only useful
change (“Also use inline-verbatim for `Message-ID`”).

Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoMerge branch 'jc/no-writev-does-not-work'
Junio C Hamano [Fri, 10 Apr 2026 23:47:35 +0000 (16:47 -0700)] 
Merge branch 'jc/no-writev-does-not-work'

We used writev() in limited code paths and supplied emulation for
platforms without working writev(), but the emulation was too
faithful to the spec to make the result useless to send even 64kB;
revert the topic and plan to restart the effort later.

* jc/no-writev-does-not-work:
  Revert "compat/posix: introduce writev(3p) wrapper"
  Revert "wrapper: introduce writev(3p) wrappers"
  Revert "sideband: use writev(3p) to send pktlines"
  Revert "cmake: use writev(3p) wrapper as needed"

2 months agoMerge branch 'ps/archive-prefix-doc'
Junio C Hamano [Fri, 10 Apr 2026 17:05:33 +0000 (10:05 -0700)] 
Merge branch 'ps/archive-prefix-doc'

Doc update.

* ps/archive-prefix-doc:
  archive: document --prefix handling of absolute and parent paths

2 months agoMerge branch 'bc/ref-storage-default-doc-update'
Junio C Hamano [Fri, 10 Apr 2026 17:05:32 +0000 (10:05 -0700)] 
Merge branch 'bc/ref-storage-default-doc-update'

Doc update.

* bc/ref-storage-default-doc-update:
  docs: correct information about reftable

2 months agorust: we are way beyond 2.53
Junio C Hamano [Fri, 10 Apr 2026 14:52:50 +0000 (07:52 -0700)] 
rust: we are way beyond 2.53

Earlier we timelined that we'd tune our build procedures to build
with Rust by default in Git 2.53, but we are already in prerelease
freeze for 2.54 now.  Update the BreakingChanges document to delay
it until Git 2.55 (slated for the end of June 2026).

Noticed-by: brian m. carlson <sandals@crustytoothpaste.net>
Helped-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agot1800: test SIGPIPE with parallel hooks
Jeff King [Fri, 10 Apr 2026 09:06:08 +0000 (12:06 +0300)] 
t1800: test SIGPIPE with parallel hooks

We recently fixed a bug in commit 2226ffaacd (run_processes_parallel():
fix order of sigpipe handling, 2026-04-08) where a hook that caused us
to get SIGPIPE would accidentally trigger the run_processes_parallel()
cleanup handler killing the child processes.

For a single hook, this meant killing the already-exited hook. This case
was triggered by our tests, but was only a problem on some platforms.

But if you have multiple hooks running in parallel, this causes a
problem everywhere, since one hook failing to read its input would take
down all hooks. Now that we have parallel hook support, we can add a
test for this case. It should pass already, due to the existing fix.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: allow hook.jobs=-1 to use all available CPU cores
Adrian Ratiu [Fri, 10 Apr 2026 09:06:07 +0000 (12:06 +0300)] 
hook: allow hook.jobs=-1 to use all available CPU cores

Allow -1 as a value for hook.jobs, hook.<event>.jobs, and the -j
CLI flag to mean "use as many jobs as there are CPU cores", matching
the convention used by fetch.parallel and other Git subsystems.

The value is resolved to online_cpus() at parse time so the rest
of the code always works with a positive resolved count.

Other non-positive values (0, -2, etc) are rejected with a warning
(config) or die (CLI).

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: add hook.<event>.enabled switch
Adrian Ratiu [Fri, 10 Apr 2026 09:06:06 +0000 (12:06 +0300)] 
hook: add hook.<event>.enabled switch

Add a hook.<event>.enabled config key that disables all hooks for
a given event, when set to false, acting as a high-level switch
above the existing per-hook hook.<friendly-name>.enabled.

Event-disabled hooks are shown in "git hook list" with an
"event-disabled" tab-separated prefix before the name:

$ git hook list test-hook
event-disabled  hook-1
event-disabled  hook-2

With --show-scope:

$ git hook list --show-scope test-hook
local   event-disabled  hook-1

When a hook is both per-hook disabled and event-disabled, only
"event-disabled" is shown: the event-level switch is the more
relevant piece of information, and the per-hook "disabled" status
will surface once the event is re-enabled.

Using an event name as a friendly-name (e.g. hook.<event>.enabled)
can cause ambiguity, so a fatal error is issued when using a known
event name and a warning is issued for unknown event name, since
a collision cannot be detected with certainty for unknown events.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: move is_known_hook() to hook.c for wider use
Adrian Ratiu [Fri, 10 Apr 2026 09:06:05 +0000 (12:06 +0300)] 
hook: move is_known_hook() to hook.c for wider use

Move is_known_hook() from builtin/hook.c (static) into hook.c and
export it via hook.h so it can be reused.

Make it return bool and the iterator `h` for clarity (iterate hooks).

Both meson.build and the Makefile are updated to reflect that the
header is now used by libgit, not the builtin sources.

The next commit will use this to reject hook friendly-names that
collide with known event names.

Co-authored-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: warn when hook.<friendly-name>.jobs is set
Adrian Ratiu [Fri, 10 Apr 2026 09:06:04 +0000 (12:06 +0300)] 
hook: warn when hook.<friendly-name>.jobs is set

Issue a warning when the user confuses the hook process and event
namespaces by setting hook.<friendly-name>.jobs.

Detect this by checking whether the name carrying .jobs also has
.command, .event, or .parallel configured.  Extract is_friendly_name()
as a helper for this check, to be reused by future per-event config
handling.

Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: add per-event jobs config
Adrian Ratiu [Fri, 10 Apr 2026 09:06:03 +0000 (12:06 +0300)] 
hook: add per-event jobs config

Add a hook.<event>.jobs count config that allows users to override the
global hook.jobs setting for specific hook events.

This allows finer-grained control over parallelism on a per-event basis.

For example, to run `post-receive` hooks with up to 4 parallel jobs
while keeping other events at their global default:

[hook]
    post-receive.jobs = 4

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: add -j/--jobs option to git hook run
Emily Shaffer [Fri, 10 Apr 2026 09:06:02 +0000 (12:06 +0300)] 
hook: add -j/--jobs option to git hook run

Expose the parallel job count as a command-line flag so callers can
request parallelism without relying only on the hook.jobs config.

Add tests covering serial/parallel execution and TTY behaviour under
-j1 vs -jN.

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: mark non-parallelizable hooks
Emily Shaffer [Fri, 10 Apr 2026 09:06:01 +0000 (12:06 +0300)] 
hook: mark non-parallelizable hooks

Several hooks are known to be inherently non-parallelizable, so initialize
them with RUN_HOOKS_OPT_INIT_FORCE_SERIAL. This pins jobs=1 and overrides
any hook.jobs or runtime -j flags.

These hooks are:
applypatch-msg, pre-commit, prepare-commit-msg, commit-msg, post-commit,
post-checkout, and push-to-checkout.

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: allow pre-push parallel execution
Adrian Ratiu [Fri, 10 Apr 2026 09:06:00 +0000 (12:06 +0300)] 
hook: allow pre-push parallel execution

pre-push is the only hook that keeps stdout and stderr separate (for
backwards compatibility with git-lfs and potentially other users). This
prevents parallelizing it because run-command needs stdout_to_stderr=1
to buffer and de-interleave parallel outputs.

Since we now default to jobs=1, backwards compatibility is maintained
without needing any extension or extra config: when no parallelism is
requested, pre-push behaves exactly as before.

When the user explicitly opts into parallelism via hook.jobs > 1,
hook.<event>.jobs > 1, or -jN, they accept the changed output behavior.

Document this and let get_hook_jobs() set stdout_to_stderr=1 automatically
when jobs > 1, removing the need for any extension infrastructure.

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: allow parallel hook execution
Emily Shaffer [Fri, 10 Apr 2026 09:05:59 +0000 (12:05 +0300)] 
hook: allow parallel hook execution

Hooks always run in sequential order due to the hardcoded jobs == 1
passed to run_process_parallel(). Remove that hardcoding to allow
users to run hooks in parallel (opt-in).

Users need to decide which hooks to run in parallel, by specifying
"parallel = true" in the config, because Git cannot know if their
specific hooks are safe to run or not in parallel (for e.g. two hooks
might write to the same file or call the same program).

Some hooks are unsafe to run in parallel by design: these will marked
in the next commit using RUN_HOOKS_OPT_INIT_FORCE_SERIAL.

The hook.jobs config specifies the default number of jobs applied to all
hooks which have parallelism enabled.

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agohook: parse the hook.jobs config
Adrian Ratiu [Fri, 10 Apr 2026 09:05:58 +0000 (12:05 +0300)] 
hook: parse the hook.jobs config

The hook.jobs config is a global way to set hook parallelization for
all hooks, in the sense that it is not per-event nor per-hook.

Finer-grained configs will be added in later commits which can override
it, for e.g. via a per-event type job options. Next commits will also
add to this item's documentation.

Parse hook.jobs config key in hook_config_lookup_all() and store its
value in hook_all_config_cb.jobs, then transfer it into r->jobs after
the config pass completes.

This is mostly plumbing and the cached value is not yet used.

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoconfig: add a repo_config_get_uint() helper
Adrian Ratiu [Fri, 10 Apr 2026 09:05:57 +0000 (12:05 +0300)] 
config: add a repo_config_get_uint() helper

Next commits add a 'hook.jobs' config option of type 'unsigned int',
so add a helper to parse it since the API only supports int and ulong.

An alternative is to make 'hook.jobs' an 'int' or parse it as an 'int'
then cast it to unsigned, however it's better to use proper helpers for
the type. Using 'ulong' is another option which already has helpers, but
it's a bit excessive in size for just the jobs number.

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agorepository: fix repo_init() memleak due to missing _clear()
Adrian Ratiu [Fri, 10 Apr 2026 09:05:56 +0000 (12:05 +0300)] 
repository: fix repo_init() memleak due to missing _clear()

There is an old pre-existing memory leak in repo_init() due to failing
to call clear_repository_format() in the error case.

It went undetected because a specific bug is required to trigger it:
enable a v1 extension in a repository with format v0. Obviously this
can only happen in a development environment, so it does not trigger
in normal usage, however the memleak is real and needs fixing.

Fix it by also calling clear_repository_format() in the error case.

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agol10n: zh_CN: post-2.53 code review
Jiang Xin [Thu, 5 Feb 2026 01:21:28 +0000 (09:21 +0800)] 
l10n: zh_CN: post-2.53 code review

Update Simplified Chinese translation for post-2.53 code review.

Reviewed-by: 依云 <lilydjwg@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2 months agoEnable Rust by default
brian m. carlson [Thu, 9 Apr 2026 22:44:34 +0000 (22:44 +0000)] 
Enable Rust by default

Our breaking changes document says that we'll enable Rust by default in
Git 2.54.  Adjust the Makefile to switch the option from WITH_RUST to
NO_RUST to enable it by default and update the help text accordingly.
Similarly, for Meson, enable the option by default and do not
automatically disable it if Cargo is missing, since the goal is to help
users find where they are likely to have problems in the future.

Update our CI tests to swap out the single Linux job with Rust to a
single job without, both for Makefile and Meson.  Similarly, update the
Windows Makefile job to not use Rust, while the Meson job (which does
not build with ci/lib.sh) will default to having it enabled.

Move the check for Cargo in the Meson build because it is no longer
needed in the main script.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoLinux: link against libdl
brian m. carlson [Thu, 9 Apr 2026 22:44:33 +0000 (22:44 +0000)] 
Linux: link against libdl

Older versions of Rust on Linux, such as that used in Debian 11 in our
CI, require linking against libdl.  Were we linking with Cargo, this
would be included automatically, but since we're not, explicitly set it
in the system-specific config.

This library is part of libc, so linking against it if it happens to be
unnecessary will add no dependencies to the resulting binary.  In
addition, it is provided by both glibc and musl, so it should be
portable to almost all Linux systems.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoci: install cargo on Alpine
brian m. carlson [Thu, 9 Apr 2026 22:44:32 +0000 (22:44 +0000)] 
ci: install cargo on Alpine

We'll make Rust the default in a future commit, so be sure to install
Cargo (which will also install Rust) to prepare for that case.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agodocs: update version with default Rust support
brian m. carlson [Thu, 9 Apr 2026 22:44:31 +0000 (22:44 +0000)] 
docs: update version with default Rust support

We missed the cut-off for Rust by default in 2.53, but we still can
enable it by default for 2.54, so update our breaking changes document
accordingly.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agowritev: retract the topic until we have a better emulation
Junio C Hamano [Thu, 9 Apr 2026 22:07:12 +0000 (15:07 -0700)] 
writev: retract the topic until we have a better emulation

The emulation layer we added for writev(3p) tries to be too faithful
to the spec that on systems with SSIZE_MAX set to lower than 64kB to
fit a single sideband packet would fail just like the real system
writev(), which makes our use of writev() for sideband messages
unworkable.

Let's revert them and reboot the effort after the release.  The
reverted commits are:

    $ git log -Swritev --oneline 8023abc632^..v2.52.0-rc1
    89152af176 cmake: use writev(3p) wrapper as needed
    26986f4cba sideband: use writev(3p) to send pktlines
    1970fcef93 wrapper: introduce writev(3p) wrappers
    3b9b2c2a29 compat/posix: introduce writev(3p) wrapper

8023abc632 is the merge of ps/upload-pack-buffer-more-writes topic to
the mainline.

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoRevert "compat/posix: introduce writev(3p) wrapper"
Junio C Hamano [Thu, 9 Apr 2026 21:48:24 +0000 (14:48 -0700)] 
Revert "compat/posix: introduce writev(3p) wrapper"

This reverts commit 3b9b2c2a29a1d529ca9884fa0a6529f6e2496abe; let's
not use writev() for now.

2 months agoRevert "wrapper: introduce writev(3p) wrappers"
Junio C Hamano [Thu, 9 Apr 2026 21:48:09 +0000 (14:48 -0700)] 
Revert "wrapper: introduce writev(3p) wrappers"

This reverts commit 1970fcef93adcc5a35f6468d00a5a634d5af2b3c; let's
not use writev() for now.

2 months agoRevert "sideband: use writev(3p) to send pktlines"
Junio C Hamano [Thu, 9 Apr 2026 21:47:51 +0000 (14:47 -0700)] 
Revert "sideband: use writev(3p) to send pktlines"

This reverts commit 26986f4cbaf38d84a82b0b35da211389ce49552c; let's
not use writev() for now.

2 months agoRevert "cmake: use writev(3p) wrapper as needed"
Junio C Hamano [Thu, 9 Apr 2026 21:47:28 +0000 (14:47 -0700)] 
Revert "cmake: use writev(3p) wrapper as needed"

This reverts commit 89152af176ea94ea8f3249115b6e00827fbbeb70; let's
not use writev() for now.

2 months agoA bit more for -rc2
Junio C Hamano [Thu, 9 Apr 2026 18:21:36 +0000 (11:21 -0700)] 
A bit more for -rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoMerge branch 'ds/rev-list-maximal-only-optim'
Junio C Hamano [Thu, 9 Apr 2026 18:21:59 +0000 (11:21 -0700)] 
Merge branch 'ds/rev-list-maximal-only-optim'

"git rev-list --maximal-only" has been optimized by borrowing the
logic used by "git show-branch --independent", which computes the
same kind of information much more efficiently.

* ds/rev-list-maximal-only-optim:
  rev-list: use reduce_heads() for --maximal-only
  p6011: add perf test for rev-list --maximal-only
  t6600: test --maximal-only and --independent

2 months agoMerge branch 'kh/doc-config-list'
Junio C Hamano [Thu, 9 Apr 2026 18:21:59 +0000 (11:21 -0700)] 
Merge branch 'kh/doc-config-list'

"git config list" is the official way to spell "git config -l" and
"git config --list".  Use it to update the documentation.

* kh/doc-config-list:
  doc: gitcvs-migration: rephrase “man page”
  doc: replace git config --list/-l with `list`

2 months agoMerge branch 'jk/c23-const-preserving-fixes-more'
Junio C Hamano [Thu, 9 Apr 2026 18:21:59 +0000 (11:21 -0700)] 
Merge branch 'jk/c23-const-preserving-fixes-more'

Further work to adjust the codebase for C23 that changes functions
like strchr() that discarded constness when they return a pointer into
a const string to preserve constness.

* jk/c23-const-preserving-fixes-more:
  git-compat-util: fix CONST_OUTPARAM typo and indentation
  refs/files-backend: drop const to fix strchr() warning
  http: drop const to fix strstr() warning
  range-diff: drop const to fix strstr() warnings
  pkt-line: make packet_reader.line non-const
  skip_prefix(): check const match between in and out params
  pseudo-merge: fix disk reads from find_pseudo_merge()
  find_last_dir_sep(): convert inline function to macro
  run-command: explicitly cast away constness when assigning to void
  pager: explicitly cast away strchr() constness
  transport-helper: drop const to fix strchr() warnings
  http: add const to fix strchr() warnings
  convert: add const to fix strchr() warnings

2 months agoMerge branch 'master' of https://github.com/git/git
Jiang Xin [Thu, 9 Apr 2026 05:48:26 +0000 (13:48 +0800)] 
Merge branch 'master' of https://github.com/git/git

Upstream adds 8 new translatable messages.

* 'master' of https://github.com/git/git: (93 commits)
  A bit more post -rc1
  ...

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
2 months agoarchive: document --prefix handling of absolute and parent paths
Pushkar Singh [Wed, 8 Apr 2026 16:00:06 +0000 (16:00 +0000)] 
archive: document --prefix handling of absolute and parent paths

Clarify that --prefix is used as given and is not normalized,
and may include leading slashes or parent directory components.

Signed-off-by: Pushkar Singh <pushkarkumarsingh1970@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agoA bit more post -rc1
Junio C Hamano [Wed, 8 Apr 2026 18:00:10 +0000 (11:00 -0700)] 
A bit more post -rc1

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2 months agorun_processes_parallel(): fix order of sigpipe handling
Jeff King [Wed, 8 Apr 2026 17:20:55 +0000 (13:20 -0400)] 
run_processes_parallel(): fix order of sigpipe handling

In commit ec0becacc9 (run-command: add stdin callback for
parallelization, 2026-01-28), we taught run_processes_parallel() to
ignore SIGPIPE, since we wouldn't want a write() to a broken pipe of one
of the children to take down the whole process.

But there's a subtle ordering issue. After we ignore SIGPIPE, we call
pp_init(), which installs its own cleanup handler for multiple signals
using sigchain_push_common(), which includes SIGPIPE. So if we receive
SIGPIPE while writing to a child, we'll trigger that handler first, pop
it off the stack, and then re-raise (which is then ignored because of
the SIG_IGN we pushed first).

But what does that handler do? It tries to clean up all of the child
processes, under the assumption that when we re-raise the signal we'll
be exiting the process!

So a hook that exits without reading all of its input will cause us to
get SIGPIPE, which will put us in a signal handler that then tries to
kill() that same child.

This seems to be mostly harmless on Linux. The process has already
exited by this point, and though kill() does not complain (since the
process has not been reaped with a wait() call), it does not affect the
exit status of the process.

However, this seems not to be true on all platforms. This case is
triggered by t5401.13, "pre-receive hook that forgets to read its
input". This test fails on NonStop since that hook was converted to the
run_processes_parallel() API.

We can fix it by reordering the code a bit. We should run pp_init()
first, and then push our SIG_IGN onto the stack afterwards, so that it
is truly ignored while feeding the sub-processes.

Note that we also reorder the popping at the end of the function, too.
This is not technically necessary, as we are doing two pops either way,
but now the pops will correctly match their pushes.

This also fixes a related case that we can't test yet. If we did have
more than one process to run, then one child causing SIGPIPE would cause
us to kill() all of the children (which might still actually be
running). But the hook API is the only user of the new feed_pipe
feature, and it does not yet support parallel hook execution. So for now
we'll always execute the processes sequentially. Once parallel hook
execution exists, we'll be able to add a test which covers this.

Reported-by: Randall S. Becker <rsbecker@nexbridge.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>