summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2026-07-06Merge branch 'ps/connected-generic-promisor-checks'Junio C Hamano3-47/+125
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
2026-07-06Merge branch 'ps/refs-onbranch-fixes'Junio C Hamano29-389/+561
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()`
2026-07-06Merge branch 'mv/log-follow-mergy'Junio C Hamano7-2/+254
"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
2026-07-06Merge branch 'wy/doc-clarify-review-replies'Junio C Hamano2-9/+48
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
2026-07-06Merge branch 'pw/status-rebase-todo'Junio C Hamano4-62/+207
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
2026-07-06Merge branch 'jk/repo-info-path-keys'Junio C Hamano6-43/+258
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
2026-07-06Merge branch 'tb/pack-path-walk-bitmap-delta-islands'Junio C Hamano5-31/+138
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
2026-07-06Merge branch 'jc/submittingpatches-design-critiques'Junio C Hamano1-0/+20
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
2026-07-06Merge branch 'kh/submittingpatches-trailers'Junio C Hamano1-10/+36
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
2026-07-06Merge branch 'mh/fetch-follow-remote-head-config'Junio C Hamano6-30/+196
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
2026-07-06Merge branch 'po/hash-object-size-t'Junio C Hamano10-19/+57
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
2026-07-06Merge branch 'ty/move-protect-hfs-ntfs'Junio C Hamano5-20/+48
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'
2026-07-06Merge branch 'ps/odb-source-packed'Junio C Hamano26-1079/+1163
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`
2026-07-06Merge branch 'td/ref-filter-restore-prefix-iteration'Junio C Hamano2-8/+44
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
2026-07-06Merge branch 'en/ort-harden-against-corrupt-trees'Junio C Hamano6-45/+249
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()
2026-07-06Merge branch 'jk/setup-gitfile-diag-fix'Junio C Hamano5-8/+9
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
2026-07-06Merge branch 'rs/cat-file-default-format-optim'Junio C Hamano1-3/+6
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
2026-07-06Merge branch 'ps/doc-recommend-b4'Junio C Hamano4-9/+114
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
2026-07-06Merge branch 'ps/setup-drop-global-state'Junio C Hamano24-75/+97
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
2026-07-06Merge branch 'cc/promisor-auto-config-url-more'Junio C Hamano7-48/+756
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'
2026-07-06Merge branch 'hn/status-pull-advice-qualified'Junio C Hamano2-8/+140
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
2026-07-06t: add greplint to detect bare grep assertionsMichael Montalbo44-5/+415
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 <mmontalbo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t: convert grep assertions to test_grepMichael Montalbo338-2806/+2815
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 <mmontalbo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t: fix Lexer line count for $() inside double-quoted stringsMichael Montalbo1-3/+6
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 <mmontalbo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t: extract chainlint's parser into shared moduleMichael Montalbo2-517/+543
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 <mmontalbo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t: fix grep assertions missing file argumentsMichael Montalbo3-3/+3
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 <mmontalbo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t/README: document test_grep helperMichael Montalbo1-0/+34
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 <mmontalbo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06sparse-index: avoid crash on intent-to-add entry outside the coneDerrick Stolee3-1/+82
When collapsing a full index to a sparse index, the recursive convert_to_sparse_rec() walks the cache tree to determine if any of the cache tree entries can be used to represent a sparse directory. As it goes, the method tracks how many cache entries are being represented by the cache tree entry. The cache tree node's 'entry_count' represents how many cache entries are covered by the node. However, this value can be negative, representing that a node is invalid, and is no longer reflecting the number of cache entries fit within. This can happen when the user uses 'git add --intent-to-add' to mark an untracked file with the intent-to-add bit to avoid committing without finishing the add. When such an intent-to-add file exists and the sparse-checkout changes to no longer contain its parent directory, this leads to a segfault. Two tests are added to demonstrate this fault: * One test is added to t3705-add-sparse-checkout.sh to demonstrate how 'git add' behaves with sparse-checkout. * One test is added to t1092-sparse-checkout-compatibility.sh to demonstrate the interaction with the sparse index and to compare it directly to how the commands behave with a full index or no sparse-checkout. The fix involves engaging with the loop that iterates over all cache entries within the parent cache tree node (from 'start' to 'end') and to set the 'span' variable slightly earlier. At this point, the cache entry is for a file that is at least one directory deeper than the current cache tree node. The path is also not in the sparse-checkout because of an earlier path_in_sparse_checkout() check above the loop. So we are trying to collapse this directory by recursively calling convert_to_sparse_rec() over that span of entries, but the negative value prevents us from predicting that number without scanning. Theoretically, we could scan to find the range of entries that match this directory and determine if they truly do have an intent-to-add bit and then collapse as many child trees as possible (the ones with valid cache tree nodes). That would be a non-trivial change for performance-only benefit. Since this combination of the intent-to-add and sparse index features has so far gone undetected by real users, this scenario is unlikely to be worth such a change. We settle for the simplest change that prevents a bug: don't try to collapse a node that is invalid for this reason. The tests that would demonstrate a segfault now pass. Further, they demonstrate that the intent-to-add bit persists in the index file after changing the sparse-checkout scope. The test in t1092 demonstrates how some sparse directories could be collapsed further with a more involved fix, if so desired in the future. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06builtin/refs: add "rename" subcommandPatrick Steinhardt4-0/+200
Add a "rename" subcommand to git-refs(1) with the syntax: $ git refs rename <oldref> <newref> It renames <oldref> together with its reflog to <newref>; even when used on a local branch ref, the current value and the reflog of the ref are the only things that are renamed. Document it and redirect casual users to "git branch -m" if that is what they wanted to do. Co-authored-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06builtin/refs: add "create" subcommandPatrick Steinhardt4-0/+209
The "update" subcommand cannot only update an existing reference, but it can also create new branches and delete existing branches by specifying the all-zeroes object ID as either old or new value. Despite that, we already have the "delete" subcommand as a handy shortcut so that a user can easily delete a branch. This relieves them of needing to understand the more arcane uses of the "update" command, and of counting the number of zeroes they need to pass. But while we have a "delete" subcommand, we don't have an equivalent that would allow the user to create a new branch, which creates a certain asymmetry. Add a new "create" subcommand to plug this gap. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06builtin/refs: add "update" subcommandPatrick Steinhardt4-0/+336
Add a new "update" subcommand which mirrors `git update-ref <refname> <oldoid> <newoid>`. This follows the same reasoning as the preceding commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06builtin/refs: add "delete" subcommandPatrick Steinhardt4-0/+221
Reference-related functionality in Git is currently spread across many different commands: git-update-ref(1), git-for-each-ref(1), git-show-ref(1), git-pack-refs(1) and git-symbolic-ref(1). This makes it hard for users to discover what functionality we have available to work with references. We have thus started to consolidate this functionality into git-refs(1), which is a toolbox of everything related to references. Until now, the command doesn't handle functionality of git-update-ref(1). Fix this gap by introducing a new "delete" subcommand, which is the equivalent of `git update-ref -d`. Note that we're intentionally not using a generic "write" subcommand with a "-d" flag. This is rather harder to discover, and subcommands that are implmented as flags tend to be hard to reason about in the code as we'd have to handle mutually-exclusive flags that stem from the other subcommand-like modes. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06builtin/refs: drop `the_repository`Patrick Steinhardt1-8/+7
We still have a couple of uses of `the_repository` in "builtin/refs.c". All of those are trivial to convert though as the command always requires a repository to exist. Convert them to use the passed-in repository and drop `USE_THE_REPOSITORY_VARIABLE`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06blame: reserve mark column only if necessaryRené Scharfe3-33/+53
git blame prepends commit hashes of boundary commits with "^", ignored commits with "?" and unblamable commits with "*" and reserves one column for them by extending the hash abbreviation, to avoid showing ambiguous hashes. This reserved column wastes precious screen space, which can be especially irritating when using the option -b to blank out boundary commit hashes and not ignoring any commits. Reserve it only as needed, i.e. if any of those cases are actually shown. Pointed-out-by: Laszlo Ersek <laszlo.ersek@posteo.net> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06gitlab-ci: enable "GIT_TEST_LONG"Patrick Steinhardt2-2/+16
Starting with 7a094d68a2 (ci: run expensive tests on push builds to integration branches, 2026-05-08) we run expensive tests in our CI for certain events. So far, this has only been wired up for GitHub Workflows though, which creates a test gap for GitLab CI. Plug this gap by also making this work for the latter. Note that these tests cannot be run on the Windows runners, as they only have 7.5GB of RAM. This is insufficient for some of the EXPENSIVE tests, so we explicitly disable "GIT_TEST_LONG" on these jobs. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06gitlab-ci: disable RAM disk on macOS jobsPatrick Steinhardt1-6/+1
When we added the macOS jobs to GitLab CI in 56090a35ab (ci: add macOS jobs to GitLab CI, 2024-01-18) we had to work around some very slow disks. This workaround essentially creates a RAM disk that we mount, where all test data is being written into RAM instead of the real disk. In the next commit though we're about to enable "GIT_TEST_LONG", which will make tests run that are marked with the "EXPENSIVE" prerequisite. This change will make a couple of tests run that write up to 8GB of data into the test output directory. As our RAM disk is only 4GB in size, this change will cause ENOSPC errors. We could accommodate for this by increasing the size of the RAM disk. In c9d708b7fc (gitlab-ci: upgrade macOS runners, 2026-05-21) we have upgraded our runners to use the "large" runners, which have 16GB of RAM available. So we could easily expand the RAM disk to a capacity of for example 12GB. But some test runs have shown that this is still quite flaky overall, as we get quite close to our limits. Instead, drop the workaround completely. This does indeed slow down execution of the test jobs: - osx-clang goes from 18 minutes to 25 minutes - osx-meson goes from 21 minutes to 33 minutes - osx-reftable stays at 21 minutes The last one seems like an outlier. The only explanation that I have is that we end up writing significantly less files with the reftable backend, which ultimately causes less I/O. Overall though, it's preferable to have something that works with the least amount of flakiness compared to having something else that is faster but unstable. Despite that, the macOS jobs aren't even the slowest jobs, so this doesn't extend the overall pipeline's length. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t: use `test_bool_env` to parse GIT_TEST_LONGPatrick Steinhardt2-3/+3
It's currently hard to explicitly disable GIT_TEST_LONG by setting it to `false`. Fix this by using `test_bool_env` instead. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t7900: clean up large EXPENSIVE repositoryPatrick Steinhardt1-25/+31
One of the tests in t7900 is marked with EXPENSIVE because we create a repository with 2GB of data that we end up repacking. We never clean up that repository though, so we occupy the full 2GB of data until the end of the test suite. Besides clogging our disk, having an EXPENSIVE test that alters the repository's state used by subsequent tests is also a bad idea, as it can easily have an impact on the heuristics used by other maintenance tasks. Adapt the test so that we create the data in a standalone repository that we clean up at the end of the test. While at it, also disable auto-maintenance so that it does not race with our manual maintenance. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t7508: skip EXPENSIVE test that is broken without SIZE_T_IS_64BITPatrick Steinhardt1-1/+1
One of the tests in t7508 is marked as EXPENSIVE because it ends up creating and adding files that are multiple gigabytes in size. This takes a while to complete, hence the EXPENSIVE prerequisite. Besides being expensive though the test can only work on systems where `size_t` is at least 64 bit. This is because one of the created files is larger than 4GB, and because Git tracks object size via `size_t` it will eventually blow up. This test has also been blowing up in the "linux32" CI job in GitHub Workflows since 7a094d68a2 (ci: run expensive tests on push builds to integration branches, 2026-05-08). But that job doesn't only fail, it also hangs, and that has been concealing the failure. Fix the issue by marking the test as requiring 64 bit `size_t`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t5608: reduce maximum disk usagePatrick Steinhardt1-31/+35
The tests in t5608 perform a couple of clones of repositories that are somewhat large. Ultimately, we end up creating: - A setup repository that contains 2GB of uncompressed pack data. - A bare clone that contains the same 2GB of data. - A clone with worktree writes a 2GB packfile and a 2GB worktree. - A second setup repository that contains a 4GB packfile. - Two 4GB clone of that repository. Some of these clones ultimately hardlink files, which ensures that we at least don't end up with more than 20GB of data. But at the end of the test we still have around 16GB of data, which is only a tiny bit better. Refactor the test to prune repositories after they have no use anymore. This reduced the peak disk usage of this test to 8GB. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t4141: fix inefficient use of dd(1)Patrick Steinhardt1-3/+2
In t4141 we generate a patch that is roughly 1GB in size to verify that git-apply(1) indeed rejects that patch. We generate that patch by prepending a patch header and then executing `test-tool genzeros` without a limit. This causes us to print infinitely many zeros, and we limit the overall amount of generated bytes via `test_copy_bytes`. This test setup is extremely expensive, as `test_copy_bytes` is implemented via `dd ibs=1 count="$1"`, which copies data one byte at a time. So as we write 1GB of data, we end up doing 1 billion reads and writes. This naturally takes a while: it takes 6 minutes on my system, and around 40 minutes in some CI jobs! We can do much better though, as genzeros already knows to handle an optional limit of how much data it is supposed to write, which allows us to remove the call to `test_copy_bytes`. Furthermore, it has already been optimized to generate the data fast. And indeed, doing this conversion drops the test execution to less than a second on my machine. That means that in theory it becomes feasible to drop the EXPENSIVE prerequisite now. But git-apply(1) still soaks up 1GB of data into memory, which may count as being expensive. Consequently, we keep the prerequisite intact. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06t0021: skip EXPENSIVE test that is broken without SIZE_T_IS_64BITPatrick Steinhardt1-1/+1
One of the tests in t0021 writes a 2GB file and then roundtrips it through the clean/sumdge filters. This test is broken on 32 bit platforms because they typically don't handle files larger then `SSIZE_MAX` well at all. While our CI has a "linux32" job that should in theory hit this issue, we never noticed it because we didn't use to run EXPENSIVE tests until 7a094d68a2 (ci: run expensive tests on push builds to integration branches, 2026-05-08). And after that commit, the test does not fail but instead hangs completely. Ideally, we'd of course properly detect this situation and then test for it. In practice, this turns out to be hard as the test failure are not reliable as they often (but not always) run into ENOMEM errors. Instead, skip the test altogether. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-06README: add GitLab CI badge to make it more discoverablePatrick Steinhardt1-1/+2
The Git project uses CI systems from both GitHub and GitLab. While both of these systems are extensively used in day-to-day work, we only have a link to the GitHub Workflows in our README, which makes the GitLab CI hard to discover. Improve the situation by adding a second badge for GitLab CI to our README. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05mingw: make `exit_process()` own the process handle on all pathsJohannes Schindelin2-3/+2
After "mingw: kill child processes in a gentler way", the ownership of the HANDLE passed to `exit_process()` and `terminate_process_tree()` is inconsistent. `terminate_process_tree()` always closes the handle; `exit_process()` closes it on success and on the terminate-tree fallback, but leaks it on the early return where GetExitCodeProcess() fails or reports the process is no longer STILL_ACTIVE. `mingw_kill()` compensated by closing the handle on its own error path, which is a double-close on every error path that does not hit that one leaky branch -- the callee has already closed the handle by then. Coverity flagged the resulting use-after-free as CID 1437238. Pin down the invariant that `exit_process()` and `terminate_process_tree()` own the handle from the call onward and close it on every return path; with that, the bogus close in `mingw_kill()` goes away. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05fsmonitor: plug token-data leak on early daemon-startup failuresJohannes Schindelin1-0/+2
`fsmonitor_run_daemon()` allocates `state.current_token_data` before any subordinate setup step that may fail (alias resolution, listener/health constructors, asynchronous IPC server init). On the successful path the listener thread takes ownership and clears the field during its teardown, so the `done:` cleanup block sees a NULL pointer. On every early-error path, however, control jumps straight to `done:` with the freshly allocated token data still referenced, and it is never freed, as Coverity flagged. Free it at the top of `done:` and clear the pointer. The success path is a no-op (the pointer is already NULL there); the error paths now drop the otherwise-leaked allocation. `fsmonitor_free_token_data()` is NULL-safe and asserts `client_ref_count == 0`, which holds trivially here because the IPC server has not yet begun accepting clients when these failures occur. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05reftable/table: release filter on error pathJohannes Schindelin1-0/+4
`reftable_table_refs_for_unindexed()` allocates a filtering_ref_iterator and then calls `reftable_buf_add()` to populate its oid buffer. On success ownership is transferred to the output iterator, but if `reftable_buf_add()` fails, the goto-out cleanup only frees the table iterator and walks away from both the filter allocation and the oid buffer that `reftable_buf_add()` may have grown. Release filter->oid and free filter alongside the existing table iterator cleanup. Reported by Coverity as CID 1671512 ("Resource leak"). Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05imap-send: avoid leaking the IMAP upload bufferJohannes Schindelin1-0/+1
When uploading messages via libcurl, `curl_append_msgs_to_imap()` accumulates each one in a strbuf that grows across loop iterations but is never released before the function returns. Release it alongside the existing libcurl cleanup. Reported by Coverity as CID 1671507 ("Resource leak"). Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05worktree: fix resource leaks when branch creation failsJohannes Schindelin1-2/+5
In the "add" subcommand, when `run_command()` fails while creating a new branch (line 948), the function returns -1 immediately without freeing the allocations made earlier: path (from prefix_filename at line 858), opt_track, branch_to_free, and new_branch_to_free. Redirect the error return through the existing cleanup block at the end of the function so all four allocations are properly freed. Pointed out by Coverity. Assisted-by: Claude Opus 4.6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05submodule: fix cwd leak in `get_superproject_working_tree()`Johannes Schindelin1-9/+10
`get_superproject_working_tree()` allocates cwd via `xgetcwd()` at the top of the function, but two early-return paths (when not inside a work tree, and when strbuf_realpath for "../" fails) return 0 without freeing it. Redirect these early returns through a cleanup label that frees cwd before returning. Pointed out by Coverity. Assisted-by: Claude Opus 4.6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-05dir: free allocations on parse-error paths in `read_one_dir()`Johannes Schindelin1-2/+7
Two of `read_one_dir()`'s parse-error early returns leak ud.untracked and ud.dirs. Plug them. The other early returns in the same function are fine: they occur after the `xmalloc()`+`memcpy()` that copies ud into `*untracked_`, at which point ownership is transferred to the caller. `read_untracked_extension()` then releases everything via `free_untracked_cache()` on failure. Pointed out by Coverity. Assisted-by: Claude Opus 4.6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>