]> git.99rst.org Git - git.git/log
git.git
2 weeks agoMerge branch 'mm/test-grep-lint'
Junio C Hamano [Sun, 19 Jul 2026 17:42:17 +0000 (10:42 -0700)]
Merge branch 'mm/test-grep-lint'

The test suite has been updated to use the 'test_grep' helper instead
of bare 'grep' for test assertions, allowing file contents to be
printed on failure for easier debugging.  A new 'greplint' linter has
been introduced to detect and prevent new bare 'grep' assertions from
being added to the test suite.

* mm/test-grep-lint:
  t: add greplint to detect bare grep assertions
  t: convert grep assertions to test_grep
  t: fix Lexer line count for $() inside double-quoted strings
  t: extract chainlint's parser into shared module
  t: fix grep assertions missing file arguments
  t/README: document test_grep helper

2 weeks agoMerge branch 'sn/osxkeychain-rust-universal'
Junio C Hamano [Sun, 19 Jul 2026 17:42:16 +0000 (10:42 -0700)]
Merge branch 'sn/osxkeychain-rust-universal'

The build system has been updated to support building universal macOS
binaries when 'Rust' is enabled, by compiling separate static archives
for each target triple listed in 'RUST_TARGETS' and combining them
using the macOS 'lipo' tool.  The 'git-credential-osxkeychain' helper
has been updated to link against '$(RUST_LIB)' when 'Rust' is enabled.

* sn/osxkeychain-rust-universal:
  contrib: wire up osxkeychain in contrib/Makefile on macOS
  Makefile: support universal macOS builds via RUST_TARGETS
  Makefile: add $(RUST_LIB) prerequisite to osxkeychain

2 weeks agoMerge branch 'bc/parse-options-exit-0-on-help'
Junio C Hamano [Sun, 19 Jul 2026 17:42:16 +0000 (10:42 -0700)]
Merge branch 'bc/parse-options-exit-0-on-help'

Option parsing with 'git rev-parse --parseopt' and in most 'git'
subcommands has been updated to exit with 0 (instead of 129) when the
help option ('-h' or '--help') is requested directly by the user,
aligning with standard Unix convention.

* bc/parse-options-exit-0-on-help:
  parse-options: exit 0 on -h
  rev-parse: have --parseopt callers exit 0 on --help
  parse-options: add a separate case for help output on error
  t1517: skip svn tests if svn is not installed

2 weeks agoMerge branch 'jc/submitting-patches-abandoning'
Junio C Hamano [Sun, 19 Jul 2026 17:42:16 +0000 (10:42 -0700)]
Merge branch 'jc/submitting-patches-abandoning'

The 'SubmittingPatches' document has been updated to explicitly
describe the expectation for contributors to retract or abandon their
patch series when they are no longer pursuing it.

* jc/submitting-patches-abandoning:
  SubmittingPatches: document how to retract a topic

2 weeks agoMerge branch 'kk/commit-reach-find-all-fix'
Junio C Hamano [Sun, 19 Jul 2026 17:42:16 +0000 (10:42 -0700)]
Merge branch 'kk/commit-reach-find-all-fix'

The early-exit optimization in 'paint_down_to_common()' has been
gated on the queue being generation-ordered, fixing a bug where
'git merge-base' (without '--all') could return incorrect results
on repositories with v1 commit graphs and clock skew.

* kk/commit-reach-find-all-fix:
  commit-reach: guard !FIND_ALL early exit with generation ordering check
  t6600: add test for merge-base early exit with clock skew

2 weeks agoMerge branch 'jc/relnotes-2.55-rust-fix'
Junio C Hamano [Sun, 19 Jul 2026 17:42:15 +0000 (10:42 -0700)]
Merge branch 'jc/relnotes-2.55-rust-fix'

A description in the release notes for Git 2.55.0 has been
retroactively updated to clarify that Rust support is enabled by
default, but still optional, and will become mandatory in Git 3.0.

* jc/relnotes-2.55-rust-fix:
  Rust: fix description in Release Notes to 2.55

2 weeks agoMerge branch 'ps/setup-split-discovery-and-setup'
Junio C Hamano [Sun, 19 Jul 2026 17:42:15 +0000 (10:42 -0700)]
Merge branch 'ps/setup-split-discovery-and-setup'

The repository discovery and repository configuration phases, which
were previously intertwined in 'setup.c', have been split.  Repository
discovery has been updated to populate a 'struct repo_discovery'
without modifying the repository state, which is then taken by
repository configuration to initialize the repository, paving the way
for clean unification of repository configuration.

* ps/setup-split-discovery-and-setup:
  setup: mark `set_git_work_tree()` as file-local
  setup: pass worktree to `init_db()`
  setup: drop redundant configuration of `startup_info->have_repository`
  setup: make repository discovery self-contained
  setup: propagate prefix via repository discovery
  setup: drop static `cwd` variable
  setup: move prefix into repository
  setup: embed repository format in discovery
  setup: introduce explicit repository discovery
  setup: split up concerns of `setup_git_env_internal()`
  setup: unify setup of shallow file
  setup: mark bogus worktree in `apply_repository_format()`
  setup: rename `check_repository_format_gently()`

2 weeks agoMerge branch 'ps/reftable-hardening'
Junio C Hamano [Sun, 19 Jul 2026 17:42:14 +0000 (10:42 -0700)]
Merge branch 'ps/reftable-hardening'

The 'reftable' code has been hardened against corrupted tables by
fixing out-of-bounds writes, out-of-bounds reads, and abort calls
during parsing.

* ps/reftable-hardening:
  reftable/table: fix OOB read on truncated table
  reftable/table: fix NULL pointer access when seeking to bogus offsets
  reftable/block: fix OOB read with bogus restart offset
  reftable/block: fix use of uninitialized memory when binsearch fails
  reftable/block: fix OOB read with bogus restart count
  reftable/block: fix OOB read with bogus block size
  reftable/block: fix OOB write with bogus inflated log size
  t/unit-tests: introduce test helper to write reftable blocks
  reftable/record: don't abort when decoding invalid ref value type
  reftable/basics: fix OOB read on binary search of empty range
  oss-fuzz: add fuzzer for parsing reftables
  meson: support building fuzzers with libFuzzer

2 weeks agoThe 4th batch for Git 2.56
Junio C Hamano [Fri, 17 Jul 2026 04:31:50 +0000 (21:31 -0700)]
The 4th batch for Git 2.56

Signed-off-by: Junio C Hamano <redacted>
2 weeks agoMerge branch 'mm/sideband-ansi-sgr-colon-fix'
Junio C Hamano [Fri, 17 Jul 2026 06:05:48 +0000 (23:05 -0700)]
Merge branch 'mm/sideband-ansi-sgr-colon-fix'

The sideband demultiplexer has been updated to recognize ANSI SGR
escape sequences that use colon-separated subfields (e.g., for
256-color or true-color codes).

* mm/sideband-ansi-sgr-colon-fix:
  sideband: allow ANSI SGR with colon-separated subfields

2 weeks agoMerge branch 'jk/git-hash-cleanups'
Junio C Hamano [Fri, 17 Jul 2026 06:05:48 +0000 (23:05 -0700)]
Merge branch 'jk/git-hash-cleanups'

The 'git_hash_*()' wrappers have been updated to be used consistently
across the codebase instead of direct calls to members of 'struct
git_hash_algo', and 'git_hash_discard()' has been made idempotent to
simplify cleanups.

* jk/git-hash-cleanups:
  hash: check ctx->active flag in all wrapper functions
  http: use idempotent git_hash_discard()
  csum-file: use idempotent git_hash_discard()
  hash: make git_hash_discard() idempotent
  hash: document function pointers and wrappers
  hash: convert remaining direct function calls
  hash: use git_hash_init() consistently

2 weeks agoMerge branch 'ih/precompose-flex-array'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'ih/precompose-flex-array'

The UTF-8 precomposition wrapper on macOS has been updated to use a
flexible array member to represent the name of a directory entry,
preventing fortified libc checks from failing when the name is
reallocated to be larger than 'NAME_MAX' bytes.

* ih/precompose-flex-array:
  precompose_utf8: use a flex array for d_name

2 weeks agoMerge branch 'ps/t-fixes-for-git-test-long'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'ps/t-fixes-for-git-test-long'

Various test scripts have been updated to clean up large temporary
files and repositories, reducing peak disk usage during testing.
Also, expensive tests have been disabled on platforms that lack
sufficient resources (like 32-bit platforms and Windows CI runners),
and the long test suite has been enabled in GitLab CI.

* ps/t-fixes-for-git-test-long:
  gitlab-ci: enable "GIT_TEST_LONG"
  gitlab-ci: disable RAM disk on macOS jobs
  t: use `test_bool_env` to parse GIT_TEST_LONG
  t7900: clean up large EXPENSIVE repository
  t7508: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT
  t5608: reduce maximum disk usage
  t4141: fix inefficient use of dd(1)
  t0021: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT
  README: add GitLab CI badge to make it more discoverable

2 weeks agoMerge branch 'js/ci-dockerized-pid-limit'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'js/ci-dockerized-pid-limit'

Dockerized CI jobs running in private GitHub repositories have been
adjusted to use explicit process and file limits, preventing resource
exhaustion errors on private runners.

* js/ci-dockerized-pid-limit:
  ci(dockerized): raise the PID limit for private repositories

2 weeks agoMerge branch 'js/coverity-fixes'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'js/coverity-fixes'

Various resource leaks, invalid file descriptor closures, and process
handle ownership issues flagged by Coverity have been fixed.

* js/coverity-fixes:
  mingw: make `exit_process()` own the process handle on all paths
  fsmonitor: plug token-data leak on early daemon-startup failures
  reftable/table: release filter on error path
  imap-send: avoid leaking the IMAP upload buffer
  worktree: fix resource leaks when branch creation fails
  submodule: fix cwd leak in `get_superproject_working_tree()`
  dir: free allocations on parse-error paths in `read_one_dir()`
  line-log: avoid redundant copy that leaks in process_ranges
  run-command: avoid `close(-1)` in `start_command()` error paths
  download_https_uri_to_file(): do not leak fd upon failure
  loose: avoid closing invalid fd on error path
  load_one_loose_object_map(): fix resource leak

2 weeks agoMerge branch 'jk/hash-algo-leak-fixes'
Junio C Hamano [Fri, 17 Jul 2026 06:05:46 +0000 (23:05 -0700)]
Merge branch 'jk/hash-algo-leak-fixes'

Various code paths that initialize a cryptographic hash context but
bail out or finish without calling 'git_hash_final()' have been taught
to call 'git_hash_discard()' to release allocated resources, fixing
memory leaks when Git is built with non-default backends like
'OpenSSL' or 'libgcrypt'.

* jk/hash-algo-leak-fixes:
  hash: add platform-specific discard functions
  hash: fix memory leak copying sha256 gcrypt handles
  http: discard hash in dumb-http http_object_request
  check_stream_oid(): discard hash on read error
  patch-id: discard hash when done
  csum-file: provide a function to release checkpoints
  csum-file: always finalize or discard hash
  hash: add discard primitive
  csum-file: drop discard_hashfile()

2 weeks agoMerge branch 'js/wincred-fixes'
Junio C Hamano [Fri, 17 Jul 2026 06:05:46 +0000 (23:05 -0700)]
Merge branch 'js/wincred-fixes'

The wincred credential helper has been updated to avoid memory
corruption when erasing credentials and to prevent silent
credential loss when storing OAuth tokens, by correcting buffer
allocations and arguments passed to safe-CRT APIs.

* js/wincred-fixes:
  wincred: prevent silent credential loss when storing OAuth tokens
  wincred: avoid memory corruption when erasing a credential

2 weeks agowincred: prevent silent credential loss when storing OAuth tokens
Johannes Schindelin [Thu, 16 Jul 2026 14:27:51 +0000 (14:27 +0000)]
wincred: prevent silent credential loss when storing OAuth tokens

When `git credential approve` hands the wincred helper a password
together with an `oauth_refresh_token`, the OAuth branch of
`store_credential()` writes one WCHAR past the allocation while
formatting both fields into a single `CredentialBlob`. On Windows
this trips heap verification and tears the helper down with status
`0xC0000374`; `approve` masks the failure, so the credential the
user meant to save never reaches `CredWriteW()` and the next
session prompts for it again.

The bug has the same shape as the one fixed in the previous commit:
the allocation leaves no room for the terminating NUL, and the
`sizeOfBuffer` argument to `_snwprintf_s()` is a byte count where
the API expects a WCHAR count, which lets the safe-CRT runtime
write the terminator out of bounds.

Apply the same remedy d22a488482 (wincred: avoid memory corruption,
2025-11-17) applied in `get_credential()`: allocate `(wlen + 1) *
sizeof(WCHAR)` bytes and pass `wlen + 1` as the destination
capacity in WCHARs.

This closes the second of the two heap writes tracked under
GHSA-rxqw-wxqg-g7hw.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
2 weeks agowincred: avoid memory corruption when erasing a credential
Johannes Schindelin [Thu, 16 Jul 2026 14:27:50 +0000 (14:27 +0000)]
wincred: avoid memory corruption when erasing a credential

The earlier d22a488482 (wincred: avoid memory corruption, 2025-11-17)
repaired only get_credential(); match_cred_password() has the same
defect and is reached on `git credential reject`. When Git asks the
helper to erase a stored credential whose password was supplied by
the caller, the helper copies the candidate's password into a freshly
allocated buffer for comparison. That copy overruns the allocation
by one WCHAR of NUL, which on uninstrumented Windows manifests as
process termination with status 0xC0000374. Because the helper can
die before reaching CredDeleteW(), `git credential reject` masks the
failure and the rejected credential remains stored.

CredentialBlobSize is documented as a byte count, so for an N-WCHAR
blob it equals N * sizeof(WCHAR). The pre-fix code allocated that
many bytes and asked wcsncpy_s to copy N wide characters, but
wcsncpy_s always appends a terminating NUL WCHAR, writing one WCHAR
past the allocation. The destination-capacity argument was also
passed in bytes rather than in WCHAR elements as the API requires,
so the safe-CRT runtime never rejected the copy.

See GHSA-rxqw-wxqg-g7hw.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
2 weeks agoMerge branch 'master' of https://github.com/j6t/git-gui
Junio C Hamano [Thu, 16 Jul 2026 17:48:52 +0000 (10:48 -0700)]
Merge branch 'master' of https://github.com/j6t/git-gui

* 'master' of https://github.com/j6t/git-gui:
  git-gui: allow larger width for the commit message field
  git-gui: reduce complexity of the quiet msgfmt rule
  git-gui: drop msgfmt --statistics output
  git-gui i18n: Update Bulgarian translation (562t)

2 weeks agoMerge branch 'master' of https://github.com/j6t/gitk
Junio C Hamano [Thu, 16 Jul 2026 17:47:40 +0000 (10:47 -0700)]
Merge branch 'master' of https://github.com/j6t/gitk

* 'master' of https://github.com/j6t/gitk:
  gitk: make "make -s" silent
  gitk i18n: Update Bulgarian translation (329t)
  gitk: spanish translations

2 weeks agoMerge branch 'master' of github.com:alshopov/git-gui
Johannes Sixt [Thu, 16 Jul 2026 09:05:03 +0000 (11:05 +0200)]
Merge branch 'master' of github.com:alshopov/git-gui

* 'master' of github.com:alshopov/git-gui:
  git-gui: allow larger width for the commit message field

Signed-off-by: Johannes Sixt <redacted>
2 weeks agoMerge branch 'hn/silence-make-s'
Johannes Sixt [Thu, 16 Jul 2026 09:02:20 +0000 (11:02 +0200)]
Merge branch 'hn/silence-make-s'

* hn/silence-make-s:
  git-gui: reduce complexity of the quiet msgfmt rule
  git-gui: drop msgfmt --statistics output

2 weeks agoMerge branch 'spanish_pr_bis' of github.com:basuradeluis/gitkbis
Johannes Sixt [Thu, 16 Jul 2026 08:53:01 +0000 (10:53 +0200)]
Merge branch 'spanish_pr_bis' of github.com:basuradeluis/gitkbis

* 'spanish_pr_bis' of github.com:basuradeluis/gitkbis:
  gitk: spanish translations

Signed-off-by: Johannes Sixt <redacted>
2 weeks agoThe 3rd batch for Git 2.56
Junio C Hamano [Wed, 15 Jul 2026 20:24:06 +0000 (13:24 -0700)]
The 3rd batch for Git 2.56

Signed-off-by: Junio C Hamano <redacted>
2 weeks agoMerge branch 'rs/blame-abbrev-marks'
Junio C Hamano [Wed, 15 Jul 2026 20:24:19 +0000 (13:24 -0700)]
Merge branch 'rs/blame-abbrev-marks'

The alignment of commit object name abbreviations in 'git blame'
output has been optimized to reserve a column for marks (caret,
question mark, or asterisk) only when such marks are actually shown.

* rs/blame-abbrev-marks:
  blame: reserve mark column only if necessary

2 weeks agoMerge branch 'mg/meson-hook-list-buildfix'
Junio C Hamano [Wed, 15 Jul 2026 20:24:19 +0000 (13:24 -0700)]
Merge branch 'mg/meson-hook-list-buildfix'

A racy build failure under Meson has been corrected by ensuring that
the generated header file 'hook-list.h' is built before compiling
files in 'builtin_sources' that depend on it.

* mg/meson-hook-list-buildfix:
  meson: restore hook-list.h to builtin_sources

2 weeks agoMerge branch 'jk/bloom-leak-fixes'
Junio C Hamano [Wed, 15 Jul 2026 20:24:19 +0000 (13:24 -0700)]
Merge branch 'jk/bloom-leak-fixes'

Various memory leaks in the Bloom-filter code paths that are exposed
when running tests with the 'GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=1'
environment variable have been plugged.

* jk/bloom-leak-fixes:
  line-log: drop extra copy of range with bloom filters
  revision: avoid leaking bloom keyvecs with multiple traversals
  bloom: make bloom-filter slab initialization idempotent

2 weeks agoMerge branch 'ps/history-drop'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'ps/history-drop'

The experimental 'git history' command has been taught a new 'drop'
subcommand to remove a commit, with its descendants replayed onto its
parent.

* ps/history-drop:
  builtin/history: implement "drop" subcommand
  builtin/history: split handling of ref updates into two phases
  replay: expose `replay_result_queue_update()`
  reset: stop assuming that the caller passes in a clean index
  reset: allow the caller to specify the current HEAD object
  reset: introduce ability to skip updating HEAD
  reset: introduce dry-run mode
  reset: modernize flags passed to `reset_working_tree()`
  reset: rename `reset_head()`
  reset: drop `USE_THE_REPOSITORY_VARIABLE`
  read-cache: split out function to drop unmerged entries to stage 0

2 weeks agoMerge branch 'ps/odb-drop-whence'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'ps/odb-drop-whence'

The 'whence' field in 'struct object_info' has been removed.  The
backend-specific object information retrieval has been refactored into
an opt-in 'struct object_info_source' structure.

* ps/odb-drop-whence:
  odb: document object info fields
  odb: drop `whence` field from object info
  treewide: convert users of `whence` to the new source field
  odb: add `source` field to struct object_info_source
  odb: make backend-specific fields optional
  packfile: thread odb_source_packed through packed_object_info()

2 weeks agoMerge branch 'ps/refs-writing-subcommands'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'ps/refs-writing-subcommands'

The 'git refs' toolbox has been extended with new 'create', 'delete',
'update', and 'rename' subcommands to create, delete, update, and
rename references, respectively.

* ps/refs-writing-subcommands:
  builtin/refs: add "rename" subcommand
  builtin/refs: add "create" subcommand
  builtin/refs: add "update" subcommand
  builtin/refs: add "delete" subcommand
  builtin/refs: drop `the_repository`

2 weeks agoMerge branch 'jc/history-message-prep-fix'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'jc/history-message-prep-fix'

A write file stream resource leak has been fixed as part of a code
cleanup.

* jc/history-message-prep-fix:
  history: streamline message preparation and plug file stream leak

3 weeks agoThe 2nd batch for Git 2.56
Junio C Hamano [Mon, 13 Jul 2026 15:27:08 +0000 (08:27 -0700)]
The 2nd batch for Git 2.56

Signed-off-by: Junio C Hamano <redacted>
3 weeks agoMerge branch 'ps/odb-generalize-prepare'
Junio C Hamano [Mon, 13 Jul 2026 15:27:27 +0000 (08:27 -0700)]
Merge branch 'ps/odb-generalize-prepare'

The 'reprepare()' callback for object database sources has been
generalized into a 'prepare()' callback with an optional flush cache
flag, and a new 'odb_prepare()' wrapper has been introduced to allow
pre-opening object database sources.

* ps/odb-generalize-prepare:
  odb: introduce `odb_prepare()`
  odb/source: generalize `reprepare()` callback

3 weeks agoMerge branch 'kk/prio-queue-get-put-fusion'
Junio C Hamano [Mon, 13 Jul 2026 15:27:27 +0000 (08:27 -0700)]
Merge branch 'kk/prio-queue-get-put-fusion'

The lazy priority queue optimization pattern (deferring actual removal
in 'prio_queue_get()' to allow get+put fusion) has been folded
directly into 'prio_queue' itself, speeding up commit traversal
workflows and simplifying callers.

* kk/prio-queue-get-put-fusion:
  prio-queue: fold lazy_queue into prio_queue for automatic get+put fusion
  prio-queue: rename .nr to .nr_ and add accessor helpers

3 weeks agoMerge branch 'hn/branch-push-slip-advice'
Junio C Hamano [Mon, 13 Jul 2026 15:27:27 +0000 (08:27 -0700)]
Merge branch 'hn/branch-push-slip-advice'

When 'git push origin/main' or 'git branch origin main' is run, the
command is now recognized as a potential typo, and advice has been
added to offer a typo fix.

* hn/branch-push-slip-advice:
  push: suggest <remote> <branch> for a slash slip
  branch: suggest <remote>/<branch> on upstream slip

3 weeks agoMerge branch 'jk/format-patch-leakfix'
Junio C Hamano [Mon, 13 Jul 2026 15:27:26 +0000 (08:27 -0700)]
Merge branch 'jk/format-patch-leakfix'

A memory leak in the '--base' handling of 'git format-patch' has been
plugged, and the leak reporting of the test suite when running under a
TAP harness has been improved.

* jk/format-patch-leakfix:
  format-patch: fix leak of rev_info in prepare_bases()
  t: move LSan errors from stdout to stderr

3 weeks agoMerge branch 'jk/reftable-leakfix'
Junio C Hamano [Mon, 13 Jul 2026 15:27:26 +0000 (08:27 -0700)]
Merge branch 'jk/reftable-leakfix'

A memory leak in the 'reftable_writer_new()' initialization function
has been fixed by delaying the allocation of 'struct reftable_writer'
until after input options are validated.

* jk/reftable-leakfix:
  reftable: fix unlikely leak on API error

3 weeks agoMerge branch 'ad/gpg-strip-cr-before-lf'
Junio C Hamano [Mon, 13 Jul 2026 15:27:26 +0000 (08:27 -0700)]
Merge branch 'ad/gpg-strip-cr-before-lf'

The GPG and SSH signature parsing code has been corrected to strip
carriage return characters only when they immediately precede line
feeds, instead of unconditionally stripping all carriage returns.

* ad/gpg-strip-cr-before-lf:
  gpg-interface: fix strip_cr_before_lf to only remove CR before LF

3 weeks agomailmap: map Taylor Blau's work address
Taylor Blau [Thu, 9 Jul 2026 02:26:20 +0000 (19:26 -0700)]
mailmap: map Taylor Blau's work address

Signed-off-by: Taylor Blau <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoSubmittingPatches: document how to retract a topic
Junio C Hamano [Wed, 8 Jul 2026 17:09:49 +0000 (10:09 -0700)]
SubmittingPatches: document how to retract a topic

While this document outlines an idealized lifecycle where an author
develops a patch, refines it with reviewer feedback, and
successfully merges it into Git, reality is rarely so seamless.

Sometimes, a topic must be abandoned. Doing so explicitly is far
better than leaving it in limbo, especially since topics can always
be resurrected later.

Clearly state that we encourage contributors to retract any topic
that does not pan out.

Signed-off-by: Junio C Hamano <redacted>
3 weeks agocontrib: wire up osxkeychain in contrib/Makefile on macOS
Shardul Natu [Wed, 8 Jul 2026 03:21:19 +0000 (03:21 +0000)]
contrib: wire up osxkeychain in contrib/Makefile on macOS

When running "make test" with TEST_CONTRIB_TOO=yes (which is default in
macOS CI workflows), $(MAKE) -C contrib/ test is invoked. However,
contrib/Makefile only invoked tests for diff-highlight and subtree,
meaning git-credential-osxkeychain was never built or verified during
standard CI test runs.

Add a "test" target to contrib/credential/osxkeychain/Makefile that
depends on building git-credential-osxkeychain. Additionally, wire up
credential/osxkeychain in contrib/Makefile under "all", "test", and
"clean" whenever running on macOS (Darwin).

This ensures that running "make test" or "make all" in contrib on macOS
automatically builds and links git-credential-osxkeychain, preventing
future build or symbol linking regressions from slipping through CI.

Signed-off-by: Shardul Natu <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoMakefile: support universal macOS builds via RUST_TARGETS
Shardul Natu [Wed, 8 Jul 2026 03:21:18 +0000 (03:21 +0000)]
Makefile: support universal macOS builds via RUST_TARGETS

On macOS, Universal Binaries contain native executable code for
multiple architectures (such as Intel x86_64 and Apple Silicon arm64)
bundled into a single file. This is standard practice for macOS
distribution and CI packaging (such as internal distribution packages
or tooling like Burrito/Homebrew), allowing a single build artifact
to run natively across all Macs without Rosetta emulation or
maintaining separate packages.

When building Git C code for multiple architectures on macOS, the
Apple toolchain (clang) natively supports universal builds via
CFLAGS/LDFLAGS. When "-arch x86_64 -arch arm64" is passed, clang
automatically compiles and links universal binaries for all C object
files and executables out of the box.

Cargo and rustc, however, do not support multiple "-arch" flags or
emitting universal binaries in a single invocation. Instead, Cargo
requires invoking each target triple independently (e.g., passing
"--target x86_64-apple-darwin" and "--target aarch64-apple-darwin").

To bridge this gap when Rust is enabled:
  1. Allow specifying space-separated target triples in RUST_TARGETS.
  2. Introduce declarative pattern rules (target/%/...) to compile
     each target-specific library slice via Cargo.
  3. On macOS, if multiple targets are specified, use "lipo" (part of
     the mandatory Xcode Command Line Tools) to combine the resulting
     static libraries into target/release/libgitcore.a.

Once $(RUST_LIB) is compiled into a universal static archive, the
standard C linker seamlessly links it with the C object files to
produce universal Git executables.

Signed-off-by: Shardul Natu <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoMakefile: add $(RUST_LIB) prerequisite to osxkeychain
Shardul Natu [Wed, 8 Jul 2026 03:21:17 +0000 (03:21 +0000)]
Makefile: add $(RUST_LIB) prerequisite to osxkeychain

When Rust is enabled, the git-credential-osxkeychain helper depends on
Rust symbols compiled into $(RUST_LIB). While commit 522ea8ef7d
("osxkeychain: fix build with Rust") updated the linker command line to
use $(LIBS), it omitted $(RUST_LIB) from the target prerequisite list.
Without this prerequisite, running a parallel build ("make -j") from a
clean working tree can fail because Make does not know to invoke Cargo
to build libgitcore.a before linking git-credential-osxkeychain.

Note that we depend explicitly on $(LIB_FILE) and $(RUST_LIB) rather
than $(GITLIBS). Unlike standard Git builtins and programs like scalar
(which define cmd_main() and rely on common-main.o to supply main()),
git-credential-osxkeychain.c defines its own standalone int main().
If $(GITLIBS) were used, $(filter %.o,$^) in the link recipe would
match both git-credential-osxkeychain.o and common-main.o, causing a
duplicate symbol linking error for _main on macOS.

Additionally, wrap the definitions of $(RUST_LIB) and the "rust" build
target in "ifndef NO_RUST". This ensures that when NO_RUST=1 is
specified, $(RUST_LIB) evaluates to empty, making the Rust dependency a
clean no-op without needing intermediate variables.

Signed-off-by: Shardul Natu <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: check ctx->active flag in all wrapper functions
Jeff King [Wed, 8 Jul 2026 03:53:05 +0000 (23:53 -0400)]
hash: check ctx->active flag in all wrapper functions

It only makes sense to call git_hash_update(), etc, on a hash context
that has been initialized but not yet finalized or discarded. This is an
unlikely error to make, but it's easy for us to catch it and complain.

It's especially important because it would quietly "work" for many hash
backends (like sha1dc, which is just manipulating some bytes) but would
cause undefined behavior with others (like OpenSSL, which puts the
context onto the heap). Checking the flag lets us catch problems
consistently on every build.

Note that we can't do the same for git_hash_init(). Even though it would
cause a leak to call it twice (without an intervening final/discard),
the point of the function is that the contents of the struct are
undefined before the call. But calling it twice is an even less likely
error to make, so not covering it is OK.

We leave git_hash_discard() alone, as its idempotent behavior is
convenient for callers. We _could_ try to do something similar for
git_hash_final(), allowing:

  git_hash_final(result, &ctx);
  git_hash_final(other_result, &ctx);

but it does not make much sense. After the first final() call we have
thrown away the state, so we cannot produce the same output. We could
come up with some sensible output (the null hash, or the empty hash),
but double-calls like this are more likely a bug, so our best bet is to
complain loudly (whereas the current code produces either nonsense
output or undefined behavior, depending on the backend).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohttp: use idempotent git_hash_discard()
Jeff King [Wed, 8 Jul 2026 03:53:02 +0000 (23:53 -0400)]
http: use idempotent git_hash_discard()

Now that it is OK to call git_hash_discard() even after finalizing the
hash, we no longer need the ctx_valid bool added by a2d8ea5a76 (http:
discard hash in dumb-http http_object_request, 2026-07-02).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agocsum-file: use idempotent git_hash_discard()
Jeff King [Wed, 8 Jul 2026 03:53:00 +0000 (23:53 -0400)]
csum-file: use idempotent git_hash_discard()

Now that it is safe to call git_hash_discard() even after finalizing it,
we can simplify our cleanup logic a bit. This is mostly undoing a few
bits of 64337aecde (csum-file: always finalize or discard hash,
2026-07-02):

  - We no longer need a separate free_hashfile_memory() function for
    finalize_hashfile(). It can just call free_hashfile(), which will
    now discard (or not) the hash as appropriate.

  - When f->skip_hash is set, we don't need to discard; we can rely on
    free_hashfile() to do it.

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: make git_hash_discard() idempotent
Jeff King [Wed, 8 Jul 2026 03:52:57 +0000 (23:52 -0400)]
hash: make git_hash_discard() idempotent

You must always either finalize or discard a hash context to release any
resources, but you must call only one such function. This creates extra
work for some callers, since their cleanup code paths need to know
whether they got there via their happy path (and the finalization
happened) or due to an error (in which case they need to discard).

Let's add an "active" flag that turns a redundant discard into a noop.
That lets you safely do this:

    git_hash_init(&ctx, algo);
    ...
    if (some_error)
            goto out;
    ...
    git_hash_final(result, &ctx);

  out:
    git_hash_discard(&ctx);

This should avoid future errors, and will also let us simplify a few
existing callers (in future patches).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: document function pointers and wrappers
Jeff King [Wed, 8 Jul 2026 03:52:55 +0000 (23:52 -0400)]
hash: document function pointers and wrappers

We want people to use the git_hash_*() wrappers rather than the bare
function pointers in the git_hash_algo struct. Let's document them
rather than the bare pointers, and warn people away from the pointers.
Coccinelle will eventually force the use of the wrappers, but it's
helpful to lead readers in the right direction from the start.

While we're here we can document a few other bits of wisdom I've turned
up while working in this area:

  - You have to initialize the destination of a git_hash_clone(). This
    is something we may eventually change for efficiency, but we should
    definitely document the requirement for now.

  - You must eventually finalize or discard a hash, since some backends
    may allocate resources during initialization.

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: convert remaining direct function calls
Jeff King [Wed, 8 Jul 2026 03:52:53 +0000 (23:52 -0400)]
hash: convert remaining direct function calls

The previous patch added a coccinelle rule to make sure callers always
use git_hash_init() rather than direct function pointers from the algo
struct.

Let's do the same for the rest of the git_hash_*() wrappers. I split
these out because they're a bit different: they implicitly use the algop
pointer in the git_hash_ctx. So when we convert:

  -algo->update_fn(&ctx, buf, len);
  +git_hash_update(&ctx, buf, len);

we drop the reference to algo entirely! But this is always going to be
the right thing. If "algo" does not match what is in ctx.algop, then
we'd already be invoking undefined behavior.

So in addition to making it possible to add more logic to the
git_hash_*() functions, we're avoiding the need to pass around the extra
algo pointer and make sure that it matches what's in "ctx".

The rest of the patch is the mechanical application of that coccinelle
patch, plus a minor cleanup in test-synthesize.c to drop a now-unused
function parameter (since we don't have to pass around the algo
separately anymore).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: use git_hash_init() consistently
Jeff King [Wed, 8 Jul 2026 03:52:49 +0000 (23:52 -0400)]
hash: use git_hash_init() consistently

We'd like to add more logic to git_hash_init(), but many callers skip it
and call algop->init_fn() directly. Let's make sure we're consistently
using the wrapper by adding a coccinelle rule.

Besides the coccinelle file itself, this is a purely mechanical
conversion based on the patch it generates. There should be no bare
init_fn() calls left (except for the one in the wrapper).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoparse-options: exit 0 on -h
brian m. carlson [Wed, 8 Jul 2026 00:15:57 +0000 (00:15 +0000)]
parse-options: exit 0 on -h

The standard philosophy for Unix software when a help option (such as
--help) is specified is that the software should exit 0, printing the
help output to standard output, since the standard output is for
user-requested output and the program performed the requested task
successfully.  If the user specifies an incorrect option, then the help
output should be printed to standard error (since the user has made a
mistake) and it should exit unsuccessfully.

Most of our commands currently exit 129 on receiving the -h option to
print the short help, which does not line up with the standard
philosophy above.  Let's change that to exit 0 instead.

This requires changes to a variety of tests which previously wanted the
129 exit code, so update them.  Note that because git diff does its own
option parsing, it still exits with 129, so update some of the tests to
expect either exit status.

Some commands also now pass with -h but not --help-all, so handle those
cases differently for those commands.

Signed-off-by: brian m. carlson <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agorev-parse: have --parseopt callers exit 0 on --help
brian m. carlson [Wed, 8 Jul 2026 00:15:56 +0000 (00:15 +0000)]
rev-parse: have --parseopt callers exit 0 on --help

The standard philosophy for Unix software when a help option (such as
--help) is specified is that the software should exit 0, printing the
help output to standard output, since the standard output is for
user-requested output and the program performed the requested task
successfully.  If the user specifies an incorrect option, then the help
output should be printed to standard error (since the user has made a
mistake) and it should exit unsuccessfully.

git rev-parse --parseopt properly directs the output in both of these
cases, but it currently exits 129 when it receives a --help or -h option
on the command line, which causes its invoking script to do the same.
This is not in line with the usual behavior and it causes scripts using
this command to exit unsuccessfully on --help as well.

Note that Git subcommands implemented using scripts, such as git
submodule, don't have this problem because Git itself intercepts the
--help option and runs man (or a similar tool), which then exits 0.
However, this still affects the myriad scripts that use this
functionality because Git is widespread and the --parseopt functionality
is a good way to get sensible option parsing across shells in a portable
way.

Because git rev-parse --parseopt is intended to be eval'd by the shell,
when help output is to be printed to standard output, Git actually
prints a cat command with a heredoc since the standard output is being
evaluated by the shell.  Thus, to do the right thing, simply add an
"exit 0" right after the end of the heredoc, which will cause the
invoking program to exit successfully.

The usual invocation recommended by the manual page is this:

    eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"

Thus, the fact that git rev-parse --parseopt still exits 129 in this
case is irrelevant, since the "echo exit $?" will print "exit 129", but
that will be after the "exit 0" printed by Git—and thus ignored, since
the shell will have already exited successfully.

Update the tests for this case.  Note that we no longer need to delete
only the first and last lines in some tests, so add a command to delete
the end of the heredoc as well.  We could do something clever with sed
to delete all but the last two lines or switch to head and tail, but
those would be more complicated and less readable, so just stick with
the simple approach.

In t1517, add three shell scripts to the failure case because they no
longer return 129 as expected.  In a future commit, we'll change the
expected result to exit 0 and these will become successful again.

Signed-off-by: brian m. carlson <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoparse-options: add a separate case for help output on error
brian m. carlson [Wed, 8 Jul 2026 00:15:55 +0000 (00:15 +0000)]
parse-options: add a separate case for help output on error

When we parse a command line option such as -h or --help, we currently
exit 129, since that is the exit code when help output is printed. In a
future commit, we'll change this to exit 0 instead, since we're doing
what the user wanted successfully.

However, there are some cases where we print help output because the
user has provided ambiguous or invalid input, such as an ambiguous
option, and we'll want to exit unsuccessfully there.  Make this easier
by defining a new return code, PARSE_OPT_HELP_ERROR, that can be used in
this case, while reserving PARSE_OPT_HELP for those cases where the user
has requested help directly.

Signed-off-by: brian m. carlson <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agot1517: skip svn tests if svn is not installed
brian m. carlson [Wed, 8 Jul 2026 00:15:54 +0000 (00:15 +0000)]
t1517: skip svn tests if svn is not installed

The svn tests currently assume that git-svn's option parsing will always
fail the tests because it exits 0 on --help, not 129.  However, in a
future commit, we'll expect it to exit 0 and the tests will then need to
be updated to succeed in some cases and fail in others.

We therefore need to have t1517 determine whether the Subversion Perl
modules are present, since if they are not, git-svn will die on start
and then it needs to continue to expect failure.  Add a stripped down
version of the tests in t/lib-git-svn.sh as a prerequisite we can use
here for our svn tests.

Signed-off-by: brian m. carlson <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoRust: fix description in Release Notes to 2.55
Junio C Hamano [Tue, 7 Jul 2026 17:47:39 +0000 (10:47 -0700)]
Rust: fix description in Release Notes to 2.55

Finish incomplete sentence to say that we

 - build Git 2.55 by default with Rust,
 - but you can opt out and build 2.55 without Rust,
 - but Rust will become mandatory in Git 3.0 and later.

Signed-off-by: Junio C Hamano <redacted>
3 weeks agosideband: allow ANSI SGR with colon-separated subfields
Mantas MikulÄ—nas [Wed, 13 May 2026 07:08:03 +0000 (10:08 +0300)]
sideband: allow ANSI SGR with colon-separated subfields

The SGR values used for 256-color formatting are officially defined to
be a single field with :-separated subfields (e.g. "\e[1;38:5:XX;40m")
despite the more common but kludgy use of separate values (which then
become context-dependent and lead to misinterpretation by incompatible
terminals).

Signed-off-by: Mantas MikulÄ—nas <redacted>
Acked-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoMerge branch 'jk/hash-algo-leak-fixes' into jk/git-hash-cleanups
Junio C Hamano [Tue, 7 Jul 2026 17:52:48 +0000 (10:52 -0700)]
Merge branch 'jk/hash-algo-leak-fixes' into jk/git-hash-cleanups

* jk/hash-algo-leak-fixes:
  hash: add platform-specific discard functions
  hash: fix memory leak copying sha256 gcrypt handles
  http: discard hash in dumb-http http_object_request
  check_stream_oid(): discard hash on read error
  patch-id: discard hash when done
  csum-file: provide a function to release checkpoints
  csum-file: always finalize or discard hash
  hash: add discard primitive
  csum-file: drop discard_hashfile()

3 weeks agosetup: mark `set_git_work_tree()` as file-local
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:32 +0000 (09:21 +0200)]
setup: mark `set_git_work_tree()` as file-local

In the preceding commit we have removed the last callers of
`set_git_work_tree()` that is located outside of "setup.c". Remove its
declaration and mark the function as file-local.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: pass worktree to `init_db()`
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:31 +0000 (09:21 +0200)]
setup: pass worktree to `init_db()`

In the preceding commits we have refactored how we discover and set up
repositories so that we cannot end up with partially-configured repos.
Instead, we apply the gitdir, worktree and repository format in a single
location, only.

Initializing a new repository has the same antipattern though: while
most of the information for the new repository is passed via parameters,
the work tree is instead propagated by configuring the repository's work
tree.

Refactor the code so that we also pass the work tree as an explicit
parameter. Like this, configuration fo the repository happens in a
single spot, too, just as with repository discovery.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: drop redundant configuration of `startup_info->have_repository`
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:30 +0000 (09:21 +0200)]
setup: drop redundant configuration of `startup_info->have_repository`

In `init_db()` we set `startup_info->have_repository` twice: once before
reading and applying the repository format and once after. This is
redundant though, as configuring the repository format does not rely on
this variable at all.

Remove the first such site. While at it, fix up formatting a bit.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: make repository discovery self-contained
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:29 +0000 (09:21 +0200)]
setup: make repository discovery self-contained

In the preceding commits we have introduced a separate repository
discovery phase and refactored the logic so that we have two clear
phases:

  1. Repository discovery, which doesn't modify the repository itself at
     all.

  2. Repository configuration, which takes the information we have
     discovered to set up the repository.

Extract the first phase into a new function `repo_discover()` to further
stress these two different phases.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: propagate prefix via repository discovery
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:28 +0000 (09:21 +0200)]
setup: propagate prefix via repository discovery

In the preceding commits we have started to propagate all information
required for the configuration of the repository via a new `struct
repo_discovery`. The only exception is the repository's prefix, which we
still return via the return parameter.

This is conceptually fine, but somewhat inconsistent. Refactor this to
instead propagate the prefix via the repository discovery, too.

While at it, drop a static variable in `repo_discover_bare_gitdir()`.
We apply its value to the repository discovery anyway, so we don't have
to keep it around afterwards anymore.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: drop static `cwd` variable
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:27 +0000 (09:21 +0200)]
setup: drop static `cwd` variable

The current working directory is stored as part of a static strbuf
variable. This variable had to have a lifetime longer than its
containing function because the value we return typically points into
that buffer.

In the preceding commit we have moved the prefix into the repository
though. Consequently, we can now return the repository's prefix instead
of the local one and thus properly manage the lifecycle of this local
variable.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: move prefix into repository
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:26 +0000 (09:21 +0200)]
setup: move prefix into repository

The repository prefix is currently stored in the startup info. This
feels somewhat awkward though, as it is inherently a property of a given
repository.

Move the prefix into the repository accordingly.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: embed repository format in discovery
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:25 +0000 (09:21 +0200)]
setup: embed repository format in discovery

All functions related to repository discovery receive both a `struct
repository_discovery` and `struct repository_format` as input, and the
expectation is that both will be populated. Refactor this so that the
repository format is part of the discovery result.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: introduce explicit repository discovery
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:24 +0000 (09:21 +0200)]
setup: introduce explicit repository discovery

When setting up the global repository we intermix repository discovery
and repository configuration: we repeatedly call `set_git_work_tree()`
and `apply_and_export_relative_gitdir()` until we're happy with the
result. The result of this is then a partially-configured repository
that we use for further setup.

This process is quite hard to follow, as it's never quite clear which
parts of the repository have been configured already and which haven't.
Furthermore, it means that the repository configuration is distributed
across many different places instead of having it neatly contained in a
single location. Ultimately, this is the reason that we cannot use a
central function like `repo_init()`.

Refactor the logic so that we stop partially-configuring a repository
and instead populate a new `struct repo_discovery`. This allow us to
essentially split repository setup into two phases:

  - The first phase only figures out parameters required to configure
    the repository.

  - The second phase then takes these parameters and applies them to the
    repository.

Like this, we'll never end up with a partially-configured repository and
can eventually extend `repo_init()` to handle the full initialization
for us.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: split up concerns of `setup_git_env_internal()`
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:23 +0000 (09:21 +0200)]
setup: split up concerns of `setup_git_env_internal()`

The function `setup_git_env_internal()` does two completely unrelated
things:

  - It configures the repository's gitdir and propagates environment
    variables into it.

  - It configures a couple of global parameters via environment
    variables.

The function is called when we initialize the repository's path, but
it's also called via `chdir_notify_register()` whenever we change the
current working directory. While we indeed have to reconfigure the
gitdir in case it's a relative path, it doesn't make sense to reapply
the global environment variables.

Split up concerns of this function along the above delineation. Handling
of the global environment variables is moved into `init_git()`, as they
can be considered part of our setup procedure.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: unify setup of shallow file
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:22 +0000 (09:21 +0200)]
setup: unify setup of shallow file

It is possible to configure an arbitrary "shallow" file via two
mechanisms, and the respective logic to handle these is split across two
locations:

  - Via the "GIT_SHALLOW_FILE" environment variable, which is handled in
    `setup_git_env_internal()`.

  - Via the global "--shallow-file=" command line option, which is
    handled in `handle_options()`.

We can rather easily unify this logic by not configuring the shallow
file in `handle_options()`, but instead overwriting the environment
variable. The environment variable itself is then handled inside of
`apply_repository_format()`, which is responsible for configuring a
discovered Git directory.

This new logic is similar in nature to how we handle the other global
options already, all of which end up setting an environment variable.
So for one this gives us more consistency. But more importantly, this
change means that `the_repository` will not contain any relevant state
anymore before we hit `apply_repository_format()` once we're at the end
of this patch series. Consequently, it will become possible for us to
completely discard `the_repository` and populate it anew.

Note that on first sight, this change looks like it might change the
precedence order. Before this change, we used to configure the shallow
file in the arguments handler first, and then it looks like we override
it via the environment variable. What's important to note though is the
last parameter to `set_alternate_shallow_file()`, which tells us whether
we want to overwrite a preexisting value, and when applying the value
from the environment we tell it not to overwrite preexisting values. So
in effect, the command line has precedence over the environment. After
this change, we now overwrite preexisting environment variables when we
see the argument, and consequently we keep the precedence order in tact.

With this change though we don't need the final parameter anymore that
tells `set_alternate_shallow_file()` whether or not to overwrite. We
only have a single callsite for this function now, and that function is
itself only ever called exactly once. Remove that parameter.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: mark bogus worktree in `apply_repository_format()`
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:21 +0000 (09:21 +0200)]
setup: mark bogus worktree in `apply_repository_format()`

When a repository is configured to have both "core.worktree" and
"core.bare" we emit a warning and mark the worktree configuration as
bogus so that the next call to `setup_work_tree()` will cause us to die.
This allows us to still use the misconfigured repository, at least as
long as we don't try to use its worktree.

This condition is handled in `setup_explicit_git_dir()`. In a subsequent
commit we'll refactor this function so that it doesn't receive a repo as
input anymore though, and consequently we cannot set the "bogus" bit
anymore.

Move the logic into `apply_repository_format()` instead to prepare for
this. While at it, fix up formatting a bit.

Note that this change requires us to also explicitly unset the value of
"core.worktree" in case we have the "GIT_WORK_TREE" environment variable
set. This is because the environment variable overrides the repository's
configuration, and we don't want to warn or die in case the work tree
has been configured explicitly regardless of whether or not "core.bare"
is set.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosetup: rename `check_repository_format_gently()`
Patrick Steinhardt [Tue, 7 Jul 2026 07:21:20 +0000 (09:21 +0200)]
setup: rename `check_repository_format_gently()`

The function `check_repository_format_gently()` receives a format as
input. An unknowing reader may thus suspect that this function actually
checks the passed-in format for consistency. While the function indeed
checks the repository format, it actually serves two purposes:

  - It reads the repository's format and populates the passed-in format
    with that information.

  - It then indeed checks whether the format is consistent.

Rename the function to `read_and_verify_repository_format()` to clarify
its functionality. While at it, reorder the parameters so that the
format comes first to better match other functions that pass around the
format.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoStart Git 2.56 cycle
Junio C Hamano [Mon, 6 Jul 2026 22:49:17 +0000 (15:49 -0700)]
Start Git 2.56 cycle

This time, do not forget to update GIT-VERSION-GEN to say 2.55.GIT

Signed-off-by: Junio C Hamano <redacted>
4 weeks agoMerge branch 'sg/t3420-do-not-grep-in-missing-file'
Junio C Hamano [Mon, 6 Jul 2026 22:50:25 +0000 (15:50 -0700)]
Merge branch 'sg/t3420-do-not-grep-in-missing-file'

A test checking interactions between git rebase --quit and
autostash in t3420-rebase-autostash.sh has been corrected to use
test_path_is_missing instead of ! grep on a file that shouldn't
exist in the conflicted state.

* sg/t3420-do-not-grep-in-missing-file:
  t3420-rebase-autostash: don't try to grep non-existing files

4 weeks agoMerge branch 'ps/connected-generic-promisor-checks'
Junio C Hamano [Mon, 6 Jul 2026 22:50:24 +0000 (15:50 -0700)]
Merge branch 'ps/connected-generic-promisor-checks'

The connectivity check has been refactored to search for promisor
objects in a generic way using the object database interface,
rather than iterating packfiles directly. This allows connectivity
checks to work properly in repositories that do not use packfiles.

* ps/connected-generic-promisor-checks:
  connected: search promisor objects generically
  connected: split out promisor-based connectivity check
  odb/source-packed: support flags when iterating an object prefix
  odb/source-packed: extract logic to skip certain packs

4 weeks agoMerge branch 'ps/refs-onbranch-fixes'
Junio C Hamano [Mon, 6 Jul 2026 22:50:24 +0000 (15:50 -0700)]
Merge branch 'ps/refs-onbranch-fixes'

Reference backend configuration has been updated to load lazily to
avoid recursive calls during repository initialization when 'onbranch'
configuration conditions are evaluated. This has also fixed a memory
leak and allowed the unused `chdir_notify_reparent()` machinery to be
dropped.

* ps/refs-onbranch-fixes:
  refs: protect against chicken-and-egg recursion
  refs/reftable: lazy-load configuration to fix chicken-and-egg
  reftable: split up write options
  refs/files: lazy-load configuration to fix chicken-and-egg
  refs: move parsing of "core.logAllRefUpdates" back into ref stores
  repository: free main reference database
  chdir-notify: drop unused `chdir_notify_reparent()`
  refs: unregister reference stores from "chdir_notify"
  setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
  setup: stop applying repository format twice
  setup: inline `check_and_apply_repository_format()`

4 weeks agoMerge branch 'wy/doc-clarify-review-replies'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'wy/doc-clarify-review-replies'

Documentation on community contribution guidelines has been updated to
encourage replying to review comments before rerolling, and to advise
a default limit of at most one reroll per day to give reviewers across
different time zones enough time to participate.

* wy/doc-clarify-review-replies:
  doc: advise batching patch rerolls
  doc: encourage review replies before rerolling

4 weeks agoMerge branch 'jk/repo-info-path-keys'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'jk/repo-info-path-keys'

The "git repo info" command has been taught new keys to output both
absolute and relative paths for "gitdir" and "commondir", supported by
a new path-formatting helper extracted from "git rev-parse".

* jk/repo-info-path-keys:
  repo: add path.gitdir with absolute and relative suffix formatting
  repo: add path.commondir with absolute and relative suffix formatting
  path: extract format_path() and use in rev-parse

4 weeks agoMerge branch 'mv/log-follow-mergy'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'mv/log-follow-mergy'

"git log --follow" has been updated to better handle non-linear
history, in which the path being tracked gets renamed differently in
multiple history lines.

* mv/log-follow-mergy:
  log: improve --follow following renames for non-linear history

4 weeks agoMerge branch 'pw/status-rebase-todo'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'pw/status-rebase-todo'

The display of the rebase todo list in "git status" has been
improved to correctly abbreviate object IDs for more commands and
avoid misinterpreting refs as object IDs.

* pw/status-rebase-todo:
  status: improve rebase todo list parsing
  sequencer: factor out parsing of todo commands

4 weeks agoMerge branch 'tb/pack-path-walk-bitmap-delta-islands'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'tb/pack-path-walk-bitmap-delta-islands'

The pack-objects command has been updated to support reachability
bitmaps and delta-islands concurrently with the `--path-walk` option,
allowing faster packaging by falling back to path-walk when bitmaps
cannot fully satisfy the request.

* tb/pack-path-walk-bitmap-delta-islands:
  pack-objects: support `--delta-islands` with `--path-walk`
  pack-objects: extract `record_tree_depth()` helper
  pack-objects: support reachability bitmaps with `--path-walk`
  t/perf: drop p5311's lookup-table permutation

4 weeks agoMerge branch 'jc/submittingpatches-design-critiques'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'jc/submittingpatches-design-critiques'

The documentation in SubmittingPatches has been updated to clarify how
patch contributors should respond to design and viability critiques,
and how the resolution of such critiques should be recorded in the
final commit messages.

* jc/submittingpatches-design-critiques:
  SubmittingPatches: address design critiques

4 weeks agoMerge branch 'kh/submittingpatches-trailers'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'kh/submittingpatches-trailers'

The trailer sections in SubmittingPatches have been updated to
encourage use of standard trailers.

* kh/submittingpatches-trailers:
  SubmittingPatches: note that trailer order matters
  SubmittingPatches: be consistent with trailer markup
  SubmittingPatches: document Based-on-patch-by trailer
  SubmittingPatches: discourage common Linux trailers
  SubmittingPatches: encourage trailer use for substantial help

4 weeks agoMerge branch 'mh/fetch-follow-remote-head-config'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'mh/fetch-follow-remote-head-config'

The `fetch.followRemoteHEAD` configuration variable has been added to
provide a default for the per-remote `remote.<name>.followRemoteHEAD`
setting.

* mh/fetch-follow-remote-head-config:
  fetch: fixup a misaligned comment
  fetch: add configuration variable fetch.followRemoteHEAD
  fetch: refactor do_fetch handling of followRemoteHEAD
  fetch: return 0 on known git_fetch_config
  fetch: rename function report_set_head
  t5510: cleanup remote in followRemoteHEAD dangling ref test
  doc: explain fetchRemoteHEADWarn advice
  fetch: fixup set_head advice for warn-if-not-branch

4 weeks agoMerge branch 'po/hash-object-size-t'
Junio C Hamano [Mon, 6 Jul 2026 22:50:21 +0000 (15:50 -0700)]
Merge branch 'po/hash-object-size-t'

Support for hashing loose or packed objects larger than 4GB on Windows
and other LLP64 platforms has been improved by converting object header
buffers and data-handling functions from 'unsigned long' to 'size_t'.

* po/hash-object-size-t:
  hash-object: add a >4GB/LLP64 test case using filtered input
  hash-object: add another >4GB/LLP64 test case
  hash-object --stdin: verify that it works with >4GB/LLP64
  hash algorithms: use size_t for section lengths
  object-file.c: use size_t for header lengths
  hash-object: demonstrate a >4GB/LLP64 problem

4 weeks agoMerge branch 'ty/move-protect-hfs-ntfs'
Junio C Hamano [Mon, 6 Jul 2026 22:50:21 +0000 (15:50 -0700)]
Merge branch 'ty/move-protect-hfs-ntfs'

The global configuration variables protect_hfs and protect_ntfs have
been migrated into struct repo_config_values to tie them to
per-repository configuration state.

* ty/move-protect-hfs-ntfs:
  environment: use 'repo->initialized' for repo_protect_hfs() and repo_protect_ntfs()
  environment: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'

4 weeks agoMerge branch 'ps/odb-source-packed'
Junio C Hamano [Mon, 6 Jul 2026 22:50:21 +0000 (15:50 -0700)]
Merge branch 'ps/odb-source-packed'

The packed object source has been refactored into a proper struct
odb_source.

* ps/odb-source-packed:
  odb/source-packed: drop pointer to "files" parent source
  midx: refactor interfaces to work on "packed" source
  odb/source-packed: stub out remaining functions
  odb/source-packed: wire up `freshen_object()` callback
  odb/source-packed: wire up `find_abbrev_len()` callback
  odb/source-packed: wire up `count_objects()` callback
  odb/source-packed: wire up `for_each_object()` callback
  odb/source-packed: wire up `read_object_stream()` callback
  odb/source-packed: wire up `read_object_info()` callback
  packfile: use higher-level interface to implement `has_object_pack()`
  odb/source-packed: wire up `reprepare()` callback
  odb/source-packed: wire up `close()` callback
  odb/source-packed: start converting to a proper `struct odb_source`
  odb/source-packed: store pointer to "files" instead of generic source
  packfile: move packed source into "odb/" subsystem
  packfile: split out packfile list logic
  packfile: rename `struct packfile_store` to `odb_source_packed`

4 weeks agoMerge branch 'td/ref-filter-restore-prefix-iteration'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'td/ref-filter-restore-prefix-iteration'

Commands that list branches and tags (like git branch and git tag)
have been optimized to pass the namespace prefix when initializing
their ref iterator, avoiding a loose-ref scaling regression in
repositories with many unrelated loose references.

* td/ref-filter-restore-prefix-iteration:
  ref-filter: restore prefix-scoped iteration

4 weeks agoMerge branch 'en/ort-harden-against-corrupt-trees'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'en/ort-harden-against-corrupt-trees'

The 'ort' merge backend has been hardened against corrupt trees by
ensuring it aborts under appropriate error conditions.

* en/ort-harden-against-corrupt-trees:
  cache-tree: fix verify_cache() to catch non-adjacent D/F conflicts
  merge-ort: abort merge when trees have duplicate entries
  merge-ort: free diff pairs queue in clear_or_reinit_internal_opts()
  merge-ort: drop unnecessary show_all_errors from collect_merge_info()
  merge-ort: propagate callback errors from traverse_trees_wrapper()

4 weeks agoMerge branch 'jk/setup-gitfile-diag-fix'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'jk/setup-gitfile-diag-fix'

A regression in the error diagnosis code for invalid .git files has
been fixed, avoiding a potential NULL-pointer crash when reporting
that a .git file does not point to a valid repository.

* jk/setup-gitfile-diag-fix:
  read_gitfile(): simplify NOT_A_REPO error message

4 weeks agoMerge branch 'rs/cat-file-default-format-optim'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'rs/cat-file-default-format-optim'

The default format path of git cat-file --batch has been optimized
to use strbuf_add_oid_hex() and strbuf_add_uint() instead of
strbuf_addf(), yielding a noticeable speedup.

* rs/cat-file-default-format-optim:
  cat-file: speed up default format

4 weeks agoMerge branch 'ps/doc-recommend-b4'
Junio C Hamano [Mon, 6 Jul 2026 22:50:19 +0000 (15:50 -0700)]
Merge branch 'ps/doc-recommend-b4'

Project-specific configuration for b4 has been introduced, and the
documentation has been updated to recommend using it as a
streamlined method for submitting patches.

* ps/doc-recommend-b4:
  b4: introduce configuration for the Git project
  MyFirstContribution: recommend the use of b4
  MyFirstContribution: recommend shallow threading of cover letters

4 weeks agoMerge branch 'ps/setup-drop-global-state'
Junio C Hamano [Mon, 6 Jul 2026 22:50:19 +0000 (15:50 -0700)]
Merge branch 'ps/setup-drop-global-state'

The refactoring of 'setup.c' has been continued to drop remaining
global state (`git_work_tree_cfg`, `is_bare_repository_cfg`), updating
`is_bare_repository()` to no longer implicitly rely on
`the_repository`.

* ps/setup-drop-global-state:
  treewide: drop USE_THE_REPOSITORY_VARIABLE
  environment: stop using `the_repository` in `is_bare_repository()`
  environment: split up concerns of `is_bare_repository_cfg`
  builtin/init: stop modifying `is_bare_repository_cfg`
  setup: remove global `git_work_tree_cfg` variable
  builtin/init: simplify logic to configure worktree
  builtin/init: stop modifying global `git_work_tree_cfg` variable

4 weeks agoMerge branch 'cc/promisor-auto-config-url-more'
Junio C Hamano [Mon, 6 Jul 2026 22:50:19 +0000 (15:50 -0700)]
Merge branch 'cc/promisor-auto-config-url-more'

The handling of promisor-remote protocol capability has been updated
to allow the other side to add to the list of promisor remotes via the
'promisor.acceptFromServerURL' configuration variable.

* cc/promisor-auto-config-url-more:
  doc: promisor: improve acceptFromServer entry
  promisor-remote: auto-configure unknown remotes
  promisor-remote: trust known remotes matching acceptFromServerUrl
  promisor-remote: introduce promisor.acceptFromServerUrl
  promisor-remote: add 'local_name' to 'struct promisor_info'
  urlmatch: add url_normalize_pattern() helper
  urlmatch: change 'allow_globs' arg to bool
  t5710: simplify 'mkdir X' followed by 'git -C X init'

4 weeks agoMerge branch 'hn/status-pull-advice-qualified'
Junio C Hamano [Mon, 6 Jul 2026 22:50:18 +0000 (15:50 -0700)]
Merge branch 'hn/status-pull-advice-qualified'

Advice shown by "git status" when the local branch is behind or has
diverged from its push branch has been updated to suggest "git pull
<remote> <branch>".

* hn/status-pull-advice-qualified:
  remote: qualify "git pull" advice for non-upstream compareBranches

4 weeks agot: add greplint to detect bare grep assertions
Michael Montalbo [Mon, 6 Jul 2026 05:01:58 +0000 (05:01 +0000)]
t: add greplint to detect bare grep assertions

Without a lint guard, bare grep assertions will creep back into
tests over time, defeating the previous commit's conversion.

Add greplint.pl to catch bare 'grep' used as a test assertion
(where 'test_grep' should be used) and '! test_grep' (where
'test_grep !' should be used).

greplint.pl reuses the shared shell parser from lib-shell-parser.pl
to tokenize test bodies.  The Lexer collapses heredocs, command
substitutions, and quoted strings into single tokens, so 'grep'
appearing inside these contexts is not flagged.  A flat walk over
the token stream tracks command position and pipeline state to
distinguish assertion greps from filter greps.

For double-quoted test bodies, a source-line walk counts
backslash-continuation lines that the Lexer consumes without
emitting into the body text, adjusting the reported line number
accordingly.

Add test fixtures in greplint/ (modeled on chainlint/) covering
detection of bare grep assertions, correct skipping of filters,
pipelines, redirects, command substitutions, and lint-ok annotations.

Wire into the Makefile as:
  - test-greplint: runs greplint.pl on $(T) $(THELPERS) $(TPERF)
  - check-greplint: runs greplint.pl on fixtures, diffs against expected
  - clean-greplint: removes temp dir

Add eol=lf entries in t/.gitattributes for greplint fixtures,
matching chainlint, so that check-greplint passes on Windows
where core.autocrlf would otherwise cause CRLF mismatches
between expected and actual output.

Signed-off-by: Michael Montalbo <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot: convert grep assertions to test_grep
Michael Montalbo [Mon, 6 Jul 2026 05:01:57 +0000 (05:01 +0000)]
t: convert grep assertions to test_grep

Replace bare grep with test_grep in test assertions across the
suite, including sourced test helpers (lib-*.sh, *-tests.sh).
test_grep prints the contents of the file being searched on
failure, making debugging easier than a bare grep which fails
silently.

Only assertion-style greps are converted: grep used as a filter
in pipelines, command substitutions, conditionals, or with
redirected I/O is left as-is with a "# lint-ok" annotation.
Existing '! test_grep' calls are rewritten to 'test_grep !' so
that the diagnostic output is preserved on failure.

test_grep requires the file it reads to exist, so '! grep'
assertions that inspect a file whose presence is conditional need
care.  In t5537 the '.git/shallow' file is still present after the
repack (the client remains shallow), so the assertion is
converted like any other.  In t1400 the '.git/packed-refs' file
exists only with the files backend, so its check is guarded with a
REFFILES prerequisite; the backend-agnostic 'git show-ref' check
that follows still runs under every backend.  In t7450 'git~2' is
the NTFS 8.3 short name of a '..git' file and only exists
when 8.3 short-name generation is enabled, so its check is guarded
with a 'test -f' on the path and uses test_grep inside the guard,
the same shape as t1400 (a plain test_grep would BUG when the
short name is absent).

The conversion was generated using a grep-assertion linter
(greplint.pl, added in the following commit) to identify bare
grep calls at command position.  To reproduce, from the t/
directory:

    # Step 1: annotate the two data-filter greps (grep produces
    # data, not a verdict) so the linter skips them.
    sed -i '/grep -vf before commits\.raw/s/$/ # lint-ok: data filter/' \
        t5326-multi-pack-bitmaps.sh
    sed -i '/grep -E "^\[0-9a-f\].*|| :/s/$/ # lint-ok: data filter/' \
        t5702-protocol-v2.sh

    # Step 1b: two '! grep' assertions need more than a mechanical
    # conversion; handle them by hand before the linter-driven steps
    # below so it leaves them alone.
    #
    # t1400: '.git/packed-refs' is absent under reftable, so guard the
    # check with REFFILES (a plain test_grep would BUG on the missing
    # file):
    #
    #      git update-ref -d HEAD $B &&
    #  -   ! grep "$m" .git/packed-refs &&
    #  +   if test_have_prereq REFFILES
    #  +   then
    #  +           test_grep ! "$m" .git/packed-refs
    #  +   fi &&
    #      test_must_fail git show-ref --verify -q $m
    #
    # t7450: git~2 is an NTFS 8.3 short name that exists only when
    # short-name generation is enabled, so guard the check on its
    # presence with 'test -f' and note in a comment why the path can
    # be absent (a plain test_grep would BUG when it is):
    #
    #  -   ! grep gitdir squatting-clone/d/a/git~2
    #  +   if test -f squatting-clone/d/a/git~2
    #  +   then
    #  +           test_grep ! gitdir squatting-clone/d/a/git~2
    #  +   fi

    # Step 2: reorder pre-existing '! test_grep' to 'test_grep !'
    # (must come before steps 3-4 so greplint does not see them)
    sed -i 's/! test_grep/test_grep !/' t0031-lockfile-pid.sh
    sed -i 's/! test_grep/test_grep !/' t5300-pack-object.sh
    sed -i 's/! test_grep/test_grep !/' t5319-multi-pack-index.sh

    # Step 3: convert '! grep' -> 'test_grep !'
    perl greplint.pl *.sh 2>&1 | cut -d: -f1,2 |
    while IFS=: read f l; do
        sed -i "${l}s/! *grep/test_grep !/" "$f"
    done

    # Step 4: convert remaining 'grep' -> 'test_grep'
    perl greplint.pl *.sh 2>&1 | cut -d: -f1,2 |
    while IFS=: read f l; do
        sed -i "${l}s/grep/test_grep/" "$f"
    done

To verify, run: make -C t test-greplint

Signed-off-by: Michael Montalbo <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot: fix Lexer line count for $() inside double-quoted strings
Michael Montalbo [Mon, 6 Jul 2026 05:01:56 +0000 (05:01 +0000)]
t: fix Lexer line count for $() inside double-quoted strings

scan_dqstring's post-loop newline counter re-counts newlines that
were already counted during recursive parsing of $() bodies.  This
happens because scan_dollar returns text containing newlines (from
multi-line command substitutions), and the catch-all counter at the
end of scan_dqstring counts all of them again.

Fix this by counting newlines inline as non-special characters are
consumed, and removing the post-loop catch-all.  Each newline is
now counted exactly once: literal newlines at the inline match,
line splices at the backslash handler, and $() newlines by
scan_token during the recursive parse.

This is a latent bug: any consumer that relies on token line
numbers rather than byte offsets would get incorrect results for
tokens following a multi-line $() inside a double-quoted string.
chainlint is not affected because it annotates the original body
text using byte offsets, not token line numbers.

Signed-off-by: Michael Montalbo <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot: extract chainlint's parser into shared module
Michael Montalbo [Mon, 6 Jul 2026 05:01:55 +0000 (05:01 +0000)]
t: extract chainlint's parser into shared module

Move chainlint.pl's Lexer, ShellParser, and ScriptParser into a
shared module (lib-shell-parser.pl) so other lint tools can reuse
the same shell parsing infrastructure.  A subsequent commit adds
greplint.pl, which needs the same tokenizer to correctly identify
command boundaries.

ScriptParser's check_test() becomes a no-op in the shared module.
chainlint.pl defines ChainlintParser (extending ScriptParser)
with the &&-chain check_test() implementation.

No functional change: chainlint produces the same output and
check-chainlint self-tests pass.

Signed-off-by: Michael Montalbo <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot: fix grep assertions missing file arguments
Michael Montalbo [Mon, 6 Jul 2026 05:01:54 +0000 (05:01 +0000)]
t: fix grep assertions missing file arguments

Three grep assertions were missing their file arguments, causing
them to read from empty stdin instead of the intended file:

- t2402: '! grep ...' should read from 'out', matching the
  grep on the preceding line.
- t7507: the closing quote is in the wrong place, making the
  entire 'diff --git actual' a single pattern with no file
  argument instead of pattern 'diff --git' and file 'actual'.
- t7700: '! grep ...' should read from 'packlist', matching
  the redirect on the preceding line.

Without file arguments these greps always succeed (empty stdin
matches nothing), so the assertions were not actually checking
anything.  All three tests pass with the corrected file arguments,
confirming the intended behavior is sound.

Signed-off-by: Michael Montalbo <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot/README: document test_grep helper
Michael Montalbo [Mon, 6 Jul 2026 05:01:53 +0000 (05:01 +0000)]
t/README: document test_grep helper

test_grep is a wrapper around grep for test assertions that prints
the file contents on failure for easier debugging.  It also accepts
'!' as its first argument for negation, which preserves the
diagnostic output that '! test_grep' would suppress.

Despite being widely used (and the preferred replacement for bare
grep in assertions), test_grep has no entry in t/README alongside
the other documented helpers like test_cmp and test_line_count.
Add one.

Signed-off-by: Michael Montalbo <redacted>
Signed-off-by: Junio C Hamano <redacted>
git clone https://git.99rst.org/PROJECT