aboutsummaryrefslogtreecommitdiffstats
path: root/t
AgeCommit message (Collapse)AuthorFilesLines
3 daysMerge branch 'jk/asan-bonanza'Junio C Hamano1-0/+1
Various issues detected by Asan have been corrected. * jk/asan-bonanza: t: enable ASan's strict_string_checks option fsck: avoid parse_timestamp() on buffer that isn't NUL-terminated fsck: remove redundant date timestamp check fsck: avoid strcspn() in fsck_ident() fsck: assert newline presence in fsck_ident() cache-tree: avoid strtol() on non-string buffer Makefile: turn on NO_MMAP when building with ASan pack-bitmap: handle name-hash lookups in incremental bitmaps compat/mmap: mark unused argument in git_munmap()
3 daysMerge branch 'jc/whitespace-incomplete-line'Junio C Hamano2-4/+250
Both "git apply" and "git diff" learn a new whitespace error class, "incomplete-line". * jc/whitespace-incomplete-line: attr: enable incomplete-line whitespace error for this project diff: highlight and error out on incomplete lines apply: check and fix incomplete lines whitespace: allocate a few more bits and define WS_INCOMPLETE_LINE apply: revamp the parsing of incomplete lines diff: update the way rewrite diff handles incomplete lines diff: call emit_callback ecbdata everywhere diff: refactor output of incomplete line diff: keep track of the type of the last line seen diff: correct suppress_blank_empty hack diff: emit_line_ws_markup() if/else style fix whitespace: correct bit assignment comments
3 daysMerge branch 'lo/repo-info-all'Junio C Hamano1-0/+21
"git repo info" learned "--all" option. * lo/repo-info-all: repo: add --all to git-repo-info repo: factor out field printing to dedicated function
7 daysMerge branch 'jk/ci-windows-meson-test-fix'Junio C Hamano1-0/+1
"Windows+meson" job at the GitHub Actions CI was hard to debug, as it did not show and save failed test artifacts, which has been corrected. * jk/ci-windows-meson-test-fix: ci(windows-meson-test): handle options and output like other test jobs unit-test: ignore --no-chain-lint
7 daysMerge branch 'pw/worktree-list-display-width-fix'Junio C Hamano1-13/+24
"git worktree list" attempts to show paths to worktrees while aligning them, but miscounted display columns for the paths when non-ASCII characters were involved, which has been corrected. * pw/worktree-list-display-width-fix: worktree list: quote paths worktree list: fix column spacing
7 daysMerge branch 'jk/test-mktemp-leakfix'Junio C Hamano1-1/+7
Test leakfix. * jk/test-mktemp-leakfix: test-mktemp: plug memory and descriptor leaks
7 daysMerge branch 'ad/blame-diff-algorithm'Junio C Hamano2-0/+204
"git blame" learns "--diff-algorithm=<algo>" option. * ad/blame-diff-algorithm: blame: make diff algorithm configurable xdiff: add 'minimal' to XDF_DIFF_ALGORITHM_MASK
7 daysMerge branch 'en/ort-rename-another-fix'Junio C Hamano1-8/+85
Yet another corner case fix around renames in the "ort" merge strategy. * en/ort-rename-another-fix: merge-ort: fix failing merges in special corner case merge-ort: remove debugging crud t6429: update comment to mention correct tool
9 daysMerge branch 'jx/repo-struct-utf8width-fix'Junio C Hamano2-0/+135
The "git repo structure" subcommand tried to align its output but mixed up byte count and display column width, which has been corrected. * jx/repo-struct-utf8width-fix: builtin/repo: fix table alignment for UTF-8 characters t/unit-tests: add UTF-8 width tests for CJK chars
9 daysMerge branch 'sa/replay-atomic-ref-updates'Junio C Hamano1-8/+105
"git replay" (experimental) learned to perform ref updates itself in a transaction by default, instead of emitting where each refs should point at and leaving the actual update to another command. * sa/replay-atomic-ref-updates: replay: add replay.refAction config option replay: make atomic ref updates the default behavior replay: use die_for_incompatible_opt2() for option validation
9 daysMerge branch 'bc/submodule-force-same-hash'Junio C Hamano2-0/+51
Adding a repository that uses a different hash function is a no-no, but "git submodule add" did nt prevent it, which has been corrected. * bc/submodule-force-same-hash: read-cache: drop submodule check from add_to_cache() object-file: disallow adding submodules of different hash algo
9 daysMerge branch 'jk/attr-macroexpand-wo-recursion'Junio C Hamano1-0/+20
The code to expand attribute macros has been rewritten to avoid recursion to avoid running out of stack space in an uncontrolled way. * jk/attr-macroexpand-wo-recursion: attr: avoid recursion when expanding attribute macros
13 daysMerge branch 'kn/maintenance-is-needed'Junio C Hamano2-18/+48
"git maintenance" command learned "is-needed" subcommand to tell if it is necessary to perform various maintenance tasks. * kn/maintenance-is-needed: maintenance: add 'is-needed' subcommand maintenance: add checking logic in `pack_refs_condition()` refs: add a `optimize_required` field to `struct ref_storage_be` reftable/stack: add function to check if optimization is required reftable/stack: return stack segments directly
13 daysMerge branch 'rs/diff-quiet-no-rename'Junio C Hamano1-0/+10
As "git diff --quiet" only cares about the existence of any changes, disable rename/copy detection to skip more expensive processing whose result will be discarded anyway. * rs/diff-quiet-no-rename: diff: disable rename detection with --quiet
2025-11-19Merge branch 'kn/refs-optim-cleanup'Junio C Hamano3-2/+4
Code clean-up. * kn/refs-optim-cleanup: t/pack-refs-tests: move the 'test_done' to callees refs: rename 'pack_refs_opts' to 'refs_optimize_opts' refs: move to using the '.optimize' functions
2025-11-19Merge branch 'ps/ref-peeled-tags'Junio C Hamano6-23/+106
Some ref backend storage can hold not just the object name of an annotated tag, but the object name of the object the tag points at. The code to handle this information has been streamlined. * ps/ref-peeled-tags: t7004: do not chdir around in the main process ref-filter: fix stale parsed objects ref-filter: parse objects on demand ref-filter: detect broken tags when dereferencing them refs: don't store peeled object IDs for invalid tags object: add flag to `peel_object()` to verify object type refs: drop infrastructure to peel via iterators refs: drop `current_ref_iter` hack builtin/show-ref: convert to use `reference_get_peeled_oid()` ref-filter: propagate peeled object ID upload-pack: convert to use `reference_get_peeled_oid()` refs: expose peeled object ID via the iterator refs: refactor reference status flags refs: fully reset `struct ref_iterator::ref` on iteration refs: introduce `.ref` field for the base iterator refs: introduce wrapper struct for `each_ref_fn`
2025-11-18repo: add --all to git-repo-infoLucas Seiki Oshiro1-0/+21
Add a new flag `--all` to git-repo-info for requesting values for all the available keys. By using this flag, the user can retrieve all the values instead of searching what are the desired keys for what they wants. Helped-by: Karthik Nayak <karthik.188@gmail.com> Helped-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Lucas Seiki Oshiro <lucasseikioshiro@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-18worktree list: quote pathsPhillip Wood1-1/+14
If a worktree path contains newlines or other control characters it messes up the output of "git worktree list". Fix this by using quote_path() to display the worktree path. The output of "git worktree list" is designed for human consumption, scripts should be using the "--porcelain" option so this change should not break them. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-18worktree list: fix column spacingPhillip Wood1-12/+10
The output of "git worktree list" displays a table containing the worktree path, HEAD OID and branch name for each worktree. The code aligns the columns by measuring the visual width of the worktree path when it is printed. Unfortunately it fails to use the visual width when calculating the width of the column so, if any of the paths contain a multibyte character, we can end up with excess padding between columns. The simplest fix would be to replace strlen() with utf8_strwidth() in measure_widths(). However that leaves us measuring the visual width twice and the byte length once. By caching the visual width and printing the padding separately to the worktree path, we only need to calculate the visual width once and do not need the byte length at all. The visual widths are stored in an arrays of structs rather than an array of ints as the next commit will add more struct members. Even if there are no multibyte characters in any of the paths we still print an extra space between the path and the object id as the field width is calculated as one plus the length of the path and we print an explicit space as well. This is fixed by not printing the extra space. The tests are updated to include multibyte characters in one of the worktree paths and to check the spacing of the columns. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-18test-mktemp: plug memory and descriptor leaksJeff King1-1/+7
We test xmkstemp() in our helper by just calling: xmkstemp(xstrdup(argv[1])); This leaks both the copied string as well as the descriptor returned by the function. In practice this isn't a big deal, since we immediately exit the program, but: 1. LSan will complain about the memory leak. The only reason we did not notice this in our leak-checking builds is that both of the callers in the test suite (both in t0070) pass a broken template (and expect failure). So the function calls die() before we can actually leak. But it's an accident waiting to happen if anybody adds a call which succeeds. 2. Coverity complains about the descriptor leak. There's a long list of uninteresting or false positives in Coverity's results, but since we're here we might as well fix it, too. I didn't bother adding a new test that triggers the leak. It's not even in real production code, but just in the test-helper itself. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-18unit-test: ignore --no-chain-lintJeff King1-0/+1
In the same spirit as 9faf3963b6 (t: introduce compatibility options to clar-based tests, 2024-12-13), we should ignore --no-chain-lint passed to our clar tests, since it may appear in GIT_TEST_OPTS to be used with other tests. This is particularly important on Windows CI, where --no-chain-lint is added to the test options by default, and the meson build will pass all options to the unit tests. The only reason our meson Windows CI job does not run into this currently is that it is not respecting GIT_TEST_OPTS at all! So ignoring this option is a prerequisite to fixing that situation. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-18t: enable ASan's strict_string_checks optionJeff King1-0/+1
ASan has an option to enable strict string checking, where any pointer passed to a function that expects a NUL-terminated string will be checked for that NUL termination. This can sometimes produce false positives. E.g., it is not wrong to pass a buffer with { '1', '2', '\n' } into strtoul(). Even though it is not NUL-terminated, it will stop at the newline. But in trying it out, it identified two problematic spots in our test suite (which have now been adjusted): 1. The strtol() parsing in cache-tree.c was a real potential problem, which would have been very hard to find otherwise (since it required constructing a very specific broken index file). 2. The use of string functions in fsck_ident() were false positives, because we knew that there was always a trailing newline which would stop the functions from reading off the end of the buffer. But the reasoning behind that is somewhat fragile, and silencing those complaints made the code easier to reason about. So even though this did not find any earth-shattering bugs, and even had a few false positives, I'm sufficiently convinced that its complaints are more helpful than hurtful. Let's turn it on by default (since the test suite now runs cleanly with it) and see if it ever turns up any other instances. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-17merge-ort: fix failing merges in special corner caseElijah Newren1-0/+78
At GitHub, we had a repository that was triggering git: merge-ort.c:3032: process_renames: Assertion `newinfo && !newinfo->merged.clean` failed. during git replay. This sounds similar to the somewhat recent f6ecb603ff8a (merge-ort: fix directory rename on top of source of other rename/delete, 2025-08-06), but the cause is different. Unlike that case, there are no rename-to-self situations arising in this case, and new to this case it can only be triggered during a replay operation on the 2nd or later commit being replayed, never on the first merge in the sequence. To trigger, the repository needs: * an upstream which: * renames a file to a different directory, e.g. old/file -> new/file * leaves other files remaining in the original directory (so that e.g. "old/" still exists upstream even though file has been removed from it and placed elsewhere) * a topic branch being rebased where: * a commit in the sequence: * modifies old/file * a subsequent commit in the sequence being replayed: * does NOT touch *anything* under new/ * does NOT touch old/file * DOES modify other paths under old/ * does NOT have any relevant renames that we need to detect _anywhere_ elsewhere in the tree (meaning this interacts interestingly with both directory renames and cached renames) In such a case, the assertion will trigger. The fix turns out to be surprisingly simple. I have a very vague recollection that I actually considered whether to add such an if-check years ago when I added the very similar one for oldinfo in 1b6b902d95a5 (merge-ort: process_renames() now needs more defensiveness, 2021-01-19), but I think I couldn't figure out a possible way to trigger it and was worried at the time that if I didn't know how to trigger it then I wasn't so sure that simply skipping it was correct. Waiting did give me a chance to put more thorough tests and checks into place for the rename-to-self cases a few months back, which I might not have found as easily otherwise. Anyway, put the check in place now and add a test that demonstrates the fix. Note that this bug, as demonstrated by the conditions listed above, runs at the intersection of relevant renames, trivial directory resolutions, and cached renames. All three of those optimizations are ones that unfortunately make the code (and testcases!) a bit more complex, and threading all three makes it a bit more so. However, the testcase isn't crazy enough that I'd expect no one to ever hit it in practice, and was confused why we didn't see it before. After some digging, I discovered that merge.directoryRenames=false is a workaround to this bug, and GitHub used that setting until recently (it was a "temporary" match-what-libgit2-does piece of code that lasted years longer than intended). Since the conditions I gave above for triggering this bug rule out the possibility of there being directory renames, one might assume that it shouldn't matter whether you try to detect such renames if there aren't any. However, due to commit a16e8efe5c2b (merge-ort: fix merge.directoryRenames=false, 2025-03-13), the heavy hammer used there means that merge.directoryRenames=false ALSO turns off rename caching, which is critical to triggering the bug. This becomes a bit more than an aside since... Re-reading that old commit, a16e8efe5c2b (merge-ort: fix merge.directoryRenames=false, 2025-03-13), it appears that the solution to this latest bug might have been at least a partial alternative solution to that old commit. And it may have been an improved alternative (or at least help implement one), since it may be able to avoid the heavy-handed disabling of rename cache. That might be an interesting future thing to investigate, but is not critical for the current fix. However, since I spent time digging it all up, at least leave a small comment tweak breadcrumb to help some future reader (myself or others) who wants to dig further to connect the dots a little quicker. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-17t6429: update comment to mention correct toolElijah Newren1-8/+7
A comment at the top of t6429 mentions why the test doesn't exercise git rebase or git cherry-pick. However, it claims that it uses `test-tool fast-rebase`. That was true when the comment was written, but commit f920b0289ba3 (replay: introduce new builtin, 2023-11-24) changed it to use git replay without updating this comment. We could potentially just strike this second comment, since git replay is a bona fide built-in, but perhaps the explanation about why it focuses on git replay is still useful. Update the comment to make it accurate again. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-17blame: make diff algorithm configurableAntonin Delpeuch2-0/+204
The diff algorithm used in 'git-blame(1)' is set to 'myers', without the possibility to change it aside from the `--minimal` option. There has been long-standing interest in changing the default diff algorithm to "histogram", and Git 3.0 was floated as a possible occasion for taking some steps towards that: https://lore.kernel.org/git/xmqqed873vgn.fsf@gitster.g/ As a preparation for this move, it is worth making sure that the diff algorithm is configurable where useful. Make it configurable in the `git-blame(1)` command by introducing the `--diff-algorithm` option and make honor the `diff.algorithm` config variable. Keep Myers diff as the default. Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-16builtin/repo: fix table alignment for UTF-8 charactersJiang Xin1-0/+37
The output table from "git repo structure" is misaligned when displaying UTF-8 characters (e.g., non-ASCII glyphs). E.g.: | 仓库结构 | 值 | | -------------- | ---- | | * 引用 | | | * 计数 | 67 | The previous implementation used simple width formatting with printf() which didn't properly handle multi-byte UTF-8 characters, causing misaligned table columns when displaying repository structure information. This change modifies the stats_table_print_structure function to use strbuf_utf8_align() instead of basic printf width specifiers. This ensures proper column alignment regardless of the character encoding of the content being displayed. Also add test cases for strbuf_utf8_align(), a function newly introduced in "builtin/repo.c". Signed-off-by: Jiang Xin <worldhello.net@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-16t/unit-tests: add UTF-8 width tests for CJK charsJiang Xin2-0/+98
The file "builtin/repo.c" uses utf8_strwidth() to calculate the display width of UTF-8 characters in a table, but the resulting output is still misaligned. Add test cases for both utf8_strwidth and utf8_strnwidth to verify that they correctly compute the display width for UTF-8 characters. Also updated the build configuration in Makefile and meson.build to include the new test suite in the build process. Signed-off-by: Jiang Xin <worldhello.net@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-15read-cache: drop submodule check from add_to_cache()Jeff King1-0/+1
In add_to_cache(), we treat any directories as submodules, and complain if we can't resolve their HEAD. This call to resolve_gitlink_ref() was added by f937bc2f86 (add: error appropriately on repository with no commits, 2019-04-09), with the goal of improving the error message for empty repositories. But we already resolve the submodule HEAD in index_path(), which is where we find the actual oid we're going to use. Resolving it again here introduces some downsides: 1. It's more work, since we have to open up the submodule repository's files twice. 2. There are call paths that get to index_path() without going through add_to_cache(). For instance, we'd want a similar informative message if "git diff empty" finds that it can't resolve the submodule's HEAD. (In theory we can also get there through update-index, but AFAICT it refuses to consider directories as submodules at all, and just complains about them). 3. The resolution in index_path() catches more errors that we don't handle here. In particular, it will validate that the object format for the submodule matches that of the superproject. This isn't a bug, since our call in add_to_cache() throws away the oid it gets without looking at it. But it certainly caused confusion for me when looking at where the object-format check should go. So instead of resolving the submodule HEAD in add_to_cache(), let's just teach the call in index_path() to actually produce an error message (which it already does for other cases). That's probably what f937bc2f86 should have done in the first place, and it gives us a single point of resolution when adding a submodule to the index. The resulting output is slightly more verbose, as we propagate the error up the call stack, but I think that's OK (and again, matches many other errors we get when indexing fails). I've left the text of the error message as-is, though it is perhaps overly specific. There are many reasons that resolving the submodule HEAD might fail, though outside of corruption or system errors it is probably most likely that the submodule HEAD is simply on an unborn branch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-15object-file: disallow adding submodules of different hash algobrian m. carlson2-0/+50
The design of the hash algorithm transition plan is that objects stored must be entirely in one algorithm since we lack any way to indicate a mix of algorithms. This also includes submodules, but we have traditionally not enforced this, which leads to various problems when trying to clone or check out the the submodule from the remote. Since this cannot work in the general case, restrict adding a submodule of a different algorithm to the index. Add tests for git add and git submodule add that these are rejected. Note that we cannot check this in git fsck because the malformed submodule is stored in the tree as an object ID which is either truncated (when a SHA-256 submodule is added to a SHA-1 repository) or padded with zeros (when a SHA-1 submodule is added to a SHA-256 repository). We cannot detect even the latter case because someone could have an actual submodule that actually ends in 24 zeros, which would be a false positive. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-12diff: highlight and error out on incomplete linesJunio C Hamano1-4/+63
Teach "git diff" to highlight "\ No newline at end of file" message as a whitespace error when incomplete-line whitespace error class is in effect. Thanks to the previous refactoring of complete rewrite code path, we can do this at a single place. Unlike whitespace errors in the payload where we need to annotate in line, possibly using colors, the line that has whitespace problems, we have a dedicated line already that can serve as the error message, so paint it as a whitespace error message. Also teach "git diff --check" to notice incomplete lines as whitespace errors and report when incomplete-line whitespace error class is in effect. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-12apply: check and fix incomplete linesJunio C Hamano1-0/+187
The final line of a file that lacks the terminating newline at its end is called an incomplete line. In general they are frowned upon for many reasons (imagine concatenating two files with "cat A B" and what happens when A ends in an incomplete line, for example), and text-oriented tools often mishandle such a line. Implement checks in "git apply" for incomplete lines, which is off by default for backward compatibility's sake, so that "git apply --whitespace={fix,warn,error}" can notice, warn against, and fix them. As one of the new test shows, if you modify contents on an incomplete line in the original and leave the resulting line incomplete, it is still considered a whitespace error, the reasoning being that "you'd better fix it while at it if you are making a change on an incomplete line anyway", which may controversial. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-12Merge branch 'tc/last-modified-active-paths-optimization'Junio C Hamano1-1/+1
"git last-modified" was optimized by narrowing the set of paths to follow as it dug deeper in the history. * tc/last-modified-active-paths-optimization: last-modified: implement faster algorithm
2025-11-12attr: avoid recursion when expanding attribute macrosJeff King1-0/+20
Given a set of attribute macros like: [attr]a1 a2 [attr]a2 a3 ... [attr]a300000 -text file a1 expanding the attributes for "file" requires expanding "a1" to "a2", "a2" to "a3", and so on until hitting a non-macro expansion ("-text", in this case). We implement this via recursion: fill_one() calls macroexpand_one(), which then recurses back to fill_one(). As a result, very deep macro chains like the one above can run out of stack space and cause us to segfault. The required stack space is fairly small; I needed on the order of 200,000 entries to get a segfault on Linux. So it's unlikely anybody would hit this accidentally, leaving only malicious inputs. There you can easily construct a repo which will segfault on clone (we look at attributes during the checkout step, but you'd see the same trying to do other operations, like diff in a bare repo). It's mostly harmless, since anybody constructing such a repo is only preventing victims from cloning their evil garbage, but it could be a nuisance for hosting sites. One option to prevent this is to limit the depth of recursion we'll allow. This is conceptually easy to implement, but it raises other questions: what should the limit be, and do we need a configuration knob for it? The recursion here is simple enough that we can avoid those questions by just converting it to iteration instead. Rather than iterate over the states of a match_attr in fill_one(), we'll put them all in a queue, and the expansion of each can add to the queue rather than recursing. Note that this is a LIFO queue in order to keep the same depth-first order we did with the recursive implementation. I've avoided using the word "stack" in the code because the term is already heavily used to refer to the stack of .gitattribute files that matches the tree structure of the repository. The test uses a limited stack size so we can trigger the problem with a much smaller input than the one shown above. The value here (3000) is enough to trigger the issue on my x86_64 Linux machine. Reported-by: Ben Stav <benstav@miggo.io> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-10diff: disable rename detection with --quietRené Scharfe1-0/+10
Detecting renames and copies improves diff's output. This effort is wasted if we don't show any. Disable detection in that case. This actually fixes the error code when using the options --cached, --find-copies-harder, --no-ext-diff and --quiet together: run_diff_index() indirectly calls diff-lib.c::show_modified(), which queues even non-modified entries using diff_change() because we need them for copy detection. diff_change() sets flags.has_changes, though, which causes diff_can_quit_early() to declare we're done after seeing only the very first entry -- way too soon. Using --cached, --find-copies-harder and --quiet together without --no-ext-diff was not affected even before, as it causes the flag flags.diff_from_contents to be set, which disables the optimization in a different way. Reported-by: D. Ben Knoble <ben.knoble@gmail.com> Suggested-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-10maintenance: add 'is-needed' subcommandKarthik Nayak1-16/+38
The 'git-maintenance(1)' command provides tooling to run maintenance tasks over Git repositories. The 'run' subcommand, as the name suggests, runs the maintenance tasks. When used with the '--auto' flag, it uses heuristics to determine if the required thresholds are met for running said maintenance tasks. There is however a lack of insight into these heuristics. Meaning, the checks are linked to the execution. Add a new 'is-needed' subcommand to 'git-maintenance(1)' which allows users to simply check if it is needed to run maintenance without performing it. This subcommand can check if it is needed to run maintenance without actually running it. Ideally it should be used with the '--auto' flag, which would allow users to check if the thresholds required are met. The subcommand also supports the '--task' flag which can be used to check specific maintenance tasks. While adding the respective tests in 't/t7900-maintenance.sh', remove a duplicate of the test: 'worktree-prune task with --auto honors maintenance.worktree-prune.auto'. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-10reftable/stack: add function to check if optimization is requiredKarthik Nayak1-2/+10
The reftable backend performs auto-compaction as part of its regular flow, which is required to keep the number of tables part of a stack at bay. This allows it to stay optimized. Compaction can also be triggered voluntarily by the user via the 'git pack-refs' or the 'git refs optimize' command. However, currently there is no way for the user to check if optimization is required without actually performing it. Extract out the heuristics logic from 'reftable_stack_auto_compact()' into an internal function 'update_segment_if_compaction_required()'. Then use this to add and expose `reftable_stack_compaction_required()` which will allow users to check if the reftable backend can be optimized. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-06Merge branch 'cc/fast-import-export-i18n-cleanup'Junio C Hamano1-10/+10
Messages from fast-import/export are now marked for i18n. * cc/fast-import-export-i18n-cleanup: gpg-interface: mark a string for translation fast-import: mark strings for translation fast-export: mark strings for translation gpg-interface: use left shift to define GPG_VERIFY_* gpg-interface: simplify ssh fingerprint parsing
2025-11-05Merge branch 'rz/t0450-bisect-doc-update'Junio C Hamano1-1/+0
The help text and manual page of "git bisect" command have been made consistent with each other. * rz/t0450-bisect-doc-update: bisect: update usage and docs to match each other
2025-11-05replay: add replay.refAction config optionSiddharth Asthana1-0/+46
Add a configuration variable to control the default behavior of git replay for updating references. This allows users who prefer the traditional pipeline output to set it once in their config instead of passing --ref-action=print with every command. The config variable uses string values that mirror the behavior modes: * replay.refAction = update (default): atomic ref updates * replay.refAction = print: output commands for pipeline Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Elijah Newren <newren@gmail.com> Helped-by: Christian Couder <christian.couder@gmail.com> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-05replay: make atomic ref updates the default behaviorSiddharth Asthana1-8/+59
The git replay command currently outputs update commands that can be piped to update-ref to achieve a rebase, e.g. git replay --onto main topic1..topic2 | git update-ref --stdin This separation had advantages for three special cases: * it made testing easy (when state isn't modified from one step to the next, you don't need to make temporary branches or have undo commands, or try to track the changes) * it provided a natural can-it-rebase-cleanly (and what would it rebase to) capability without automatically updating refs, similar to a --dry-run * it provided a natural low-level tool for the suite of hash-object, mktree, commit-tree, mktag, merge-tree, and update-ref, allowing users to have another building block for experimentation and making new tools However, it should be noted that all three of these are somewhat special cases; users, whether on the client or server side, would almost certainly find it more ergonomic to simply have the updating of refs be the default. For server-side operations in particular, the pipeline architecture creates process coordination overhead. Server implementations that need to perform rebases atomically must maintain additional code to: 1. Spawn and manage a pipeline between git-replay and git-update-ref 2. Coordinate stdout/stderr streams across the pipe boundary 3. Handle partial failure states if the pipeline breaks mid-execution 4. Parse and validate the update-ref command output Change the default behavior to update refs directly, and atomically (at least to the extent supported by the refs backend in use). This eliminates the process coordination overhead for the common case. For users needing the traditional pipeline workflow, add a new --ref-action=<mode> option that preserves the original behavior: git replay --ref-action=print --onto main topic1..topic2 | git update-ref --stdin The mode can be: * update (default): Update refs directly using an atomic transaction * print: Output update-ref commands for pipeline use Test suite changes: All existing tests that expected command output now use --ref-action=print to preserve their original behavior. This keeps the tests valid while allowing them to verify that the pipeline workflow still works correctly. New tests were added to verify: - Default atomic behavior (no output, refs updated directly) - Bare repository support (server-side use case) - Equivalence between traditional pipeline and atomic updates - Real atomicity using a lock file to verify all-or-nothing guarantee - Test isolation using test_when_finished to clean up state - Reflog messages include replay mode and target A following commit will add a replay.refAction configuration option for users who prefer the traditional pipeline output as their default behavior. Helped-by: Elijah Newren <newren@gmail.com> Helped-by: Patrick Steinhardt <ps@pks.im> Helped-by: Christian Couder <christian.couder@gmail.com> Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04Merge branch 'jk/doc-backslash-in-exclude'Junio C Hamano1-0/+2
The patterns used in the .gitignore files use backslash in the way documented for fnmatch(3); document as such to reduce confusion. * jk/doc-backslash-in-exclude: doc: document backslash in gitignore patterns
2025-11-04Merge branch 'jk/test-delete-gpgsig-leakfix'Junio C Hamano1-3/+4
Leakfix. * jk/test-delete-gpgsig-leakfix: test-tool: fix leak in delete-gpgsig command
2025-11-04Merge branch 'eb/t1016-hash-transition-fix'Junio C Hamano2-1/+7
Test fix. * eb/t1016-hash-transition-fix: t1016-compatObjectFormat: really freeze time for reproduciblity
2025-11-04Merge branch 'tz/test-prepare-gnupghome'Junio C Hamano1-0/+1
Tests did not set up GNUPGHOME correctly, which is fixed but some flaky tests are exposed in t1016, which needs to be addressed before this topic can move forward. * tz/test-prepare-gnupghome: t/lib-gpg: call prepare_gnupghome() in GPG2 prereq t/lib-gpg: add prepare_gnupghome() to create GNUPGHOME dir
2025-11-04Merge branch 'jt/repo-structure'Junio C Hamano2-0/+130
"git repo structure", a new command. * jt/repo-structure: builtin/repo: add progress meter for structure stats builtin/repo: add keyvalue and nul format for structure stats builtin/repo: add object counts in structure output builtin/repo: introduce structure subcommand ref-filter: export ref_kind_from_refname() ref-filter: allow NULL filter pattern builtin/repo: rename repo_info() to cmd_repo_info()
2025-11-04Merge branch 'kn/refs-optim-cleanup' into kn/maintenance-is-neededJunio C Hamano3-2/+4
* kn/refs-optim-cleanup: t/pack-refs-tests: move the 'test_done' to callees refs: rename 'pack_refs_opts' to 'refs_optimize_opts' refs: move to using the '.optimize' functions
2025-11-04Merge branch 'ps/ref-peeled-tags' into kn/maintenance-is-neededJunio C Hamano8-23/+236
* ps/ref-peeled-tags: (23 commits) t7004: do not chdir around in the main process ref-filter: fix stale parsed objects ref-filter: parse objects on demand ref-filter: detect broken tags when dereferencing them refs: don't store peeled object IDs for invalid tags object: add flag to `peel_object()` to verify object type refs: drop infrastructure to peel via iterators refs: drop `current_ref_iter` hack builtin/show-ref: convert to use `reference_get_peeled_oid()` ref-filter: propagate peeled object ID upload-pack: convert to use `reference_get_peeled_oid()` refs: expose peeled object ID via the iterator refs: refactor reference status flags refs: fully reset `struct ref_iterator::ref` on iteration refs: introduce `.ref` field for the base iterator refs: introduce wrapper struct for `each_ref_fn` builtin/repo: add progress meter for structure stats builtin/repo: add keyvalue and nul format for structure stats builtin/repo: add object counts in structure output builtin/repo: introduce structure subcommand ...
2025-11-04t/pack-refs-tests: move the 'test_done' to calleesKarthik Nayak3-2/+4
In ac0bad0af4 (t0601: refactor tests to be shareable, 2025-09-19), we refactored 't/t0601-reffiles-pack-refs.sh' to move all of the tests to 't/pack-refs-tests.sh', which became a common test suite which was also used by 't/t1463-refs-optimize.sh'. This also moved the 'test_done' directive to 't/pack-refs-tests.sh'. Which inhibits additional tests from being added to either of the tests. Let's move the directive out to both the tests, so that we can add additional specific tests to them. Also the test flow logic shouldn't be part of tests which can be embedded in other test scripts. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04t7004: do not chdir around in the main processJunio C Hamano1-18/+20
Move down to no-contains subdirectory inside a subshell, just like the previous step that created and used it does. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04ref-filter: fix stale parsed objectsPatrick Steinhardt1-0/+20
In 054f5f457e (ref-filter: parse objects on demand, 2025-10-23) we have started to skip parsing some objects in case we don't need to access their values in the first place. This was done by introducing a new member `struct expand_data::maybe_object` that gets populated on demand via `get_or_parse_object()`. This has led to a regression though where the object now gets reused because we don't reset it properly. The `oi` structure is declared in global scope, and there is no single place where we reset it before invoking `get_object()`. The consequence is that the `maybe_object` member doesn't get reset across calls, so subsequent calls will end up reusing the same object. This is only an issue for a subset of retrieved values, as not all of the infrastructure ends up calling `get_or_parse_object()`. So the effect is limited, which is probably why the issue wasn't detected earlier. Fix the issue by resetting `maybe_object` in `get_object()`. Reported-by: Junio C Hamano <gitster@pobox.com> Based-on-patch-by: Jeff King <peff@peff.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04ref-filter: detect broken tags when dereferencing themPatrick Steinhardt1-1/+3
Users can ask git-for-each-ref(1) to peel tags and return information of the tagged object by adding an asterisk to the format, like for example "%(*$objectname)". If so, git-for-each-ref(1) peels that object to the first non-tag object and then returns its values. As mentioned in preceding commits, it can happen that the tagged object type and the claimed object type differ, effectively resulting in a corrupt tag. git-for-each-ref(1) would notice this mismatch, print an error and then bail out when trying to peel the tag. But we only notice this corruption in some very specific edge cases! While we have a test in "t/for-each-ref-tests.sh" that verifies the above scenario, this test is specifically crafted to detect the issue at hand. Namely, we create two tags: - One tag points to a specific object with the correct type. - The other tag points to the *same* object with a different type. The fact that both tags point to the same object is important here: `peel_object()` wouldn't notice the corruption if the tagged objects were different. The root cause is that `peel_object()` calls `lookup_${type}()` eventually, where the type is the same type declared in the tag object. Consequently, when we have two tags pointing to the same object but with different declared types we'll call two different lookup functions. The first lookup will store the object with an unverified type A, whereas the second lookup will try to look up the object with a different unverified type B. And it is only now that we notice the discrepancy in object types, even though type A could've already been the wrong type. Fix the issue by verifying the object type in `populate_value()`. With this change we'll also notice type mismatches when only dereferencing a tag once. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04refs: don't store peeled object IDs for invalid tagsPatrick Steinhardt2-0/+60
Both the "files" and "reftable" backend store peeled object IDs for references that point to tags: - The "files" backend stores the value when packing refs, where each peeled object ID is prefixed with "^". - The "reftable" backend stores the value whenever writing a new reference that points to a tag via a special ref record type. Both of these backends use `peel_object()` to find the peeled object ID. But as explained in the preceding commit, that function does not detect the case where the tag's tagged object and its claimed type mismatch. The consequence of storing these bogus peeled object IDs is that we're less likely to detect such corruption in other parts of Git. git-for-each-ref(1) for example does not notice anymore that the tag is broken when using "--format=%(*objectname)" to dereference tags. One could claim that this is good, because it still allows us to mostly use the tag as intended. But the biggest problem here is that we now have different behaviour for such a broken tag depending on whether or not we have its peeled value in the refdb. Fix the issue by verifying the object type when peeling the object. If that verification fails we simply skip storing the peeled value in either of the reference formats. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04object: add flag to `peel_object()` to verify object typePatrick Steinhardt1-1/+1
When peeling a tag to a non-tag object we repeatedly call `parse_object()` on the tagged object until we find the first object that isn't a tag. While this feels sensible at first, there is a big catch here: `parse_object()` doesn't actually verify the type of the tagged object. The relevant code path here eventually ends up in `parse_tag_buffer()`. Here, we parse the various fields of the tag, including the "type". Once we've figured out the type and the tagged object ID, we call one of the `lookup_${type}()` functions for whatever type we have found. There is two possible outcomes in the successful case: 1. The object is already part of our cached objects. In that case we double-check whether the type we're trying to look up matches the type that was cached. 2. The object is _not_ part of our cached objects. In that case, we simply create a new object with the expected type, but we don't parse that object. In the first case we might notice type mismatches, but only in the case where our cache has the object with the correct type. In the second case, we'll blindly assume that the type is correct and then go with it. We'll only notice that the type might be wrong when we try to parse the object at a later point. Now arguably, we could change `parse_tag_buffer()` to verify the tagged object's type for us. But that would have the effect that such a tag cannot be parsed at all anymore, and we have a small bunch of tests for exactly this case that assert we still can open such tags. So this change does not feel like something we can retroactively tighten, even though one shouldn't ever hit such corrupted tags. Instead, add a new `flags` field to `peel_object()` that allows the caller to opt in to strict object verification. This will be wired up at a subset of callsites over the next few commits. Note that this change also inlines `deref_tag_noverify()`. There's only been two callsites of that function, the one we're changing and one in our test helpers. The latter callsite can trivially use `deref_tag()` instead, so by inlining the function we avoid having to pass down the flag. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-04refs: introduce wrapper struct for `each_ref_fn`Patrick Steinhardt1-3/+2
The `each_ref_fn` callback function type is used across our code base for several different functions that iterate through reference. There's a bunch of callbacks implementing this type, which makes any changes to the callback signature extremely noisy. An example of the required churn is e8207717f1 (refs: add referent to each_ref_fn, 2024-08-09): adding a single argument required us to change 48 files. It was already proposed back then [1] that we might want to introduce a wrapper structure to alleviate the pain going forward. While this of course requires the same kind of global refactoring as just introducing a new parameter, it at least allows us to more change the callback type afterwards by just extending the wrapper structure. One counterargument to this refactoring is that it makes the structure more opaque. While it is obvious which callsites need to be fixed up when we change the function type, it's not obvious anymore once we use a structure. That being said, we only have a handful of sites that actually need to populate this wrapper structure: our ref backends, "refs/iterator.c" as well as very few sites that invoke the iterator callback functions directly. Introduce this wrapper structure so that we can adapt the iterator interfaces more readily. [1]: <ZmarVcF5JjsZx0dl@tanuki> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-03last-modified: implement faster algorithmToon Claes1-1/+1
The current implementation of git-last-modified(1) works by doing a revision walk, and inspecting the diff at each level of that walk to annotate entries remaining in the hashmap of paths. In other words, if the diff at some level touches a path which has not yet been associated with a commit, then that commit becomes associated with the path. While a perfectly reasonable implementation, it can perform poorly in either one of two scenarios: 1. There are many entries of interest, in which case there is simply a lot of work to do. 2. Or, there are (even a few) entries which have not been updated in a long time, and so we must walk through a lot of history in order to find a commit that touches that path. This patch rewrites the last-modified implementation that addresses the second point. The idea behind the algorithm is to propagate a set of 'active' paths (a path is 'active' if it does not yet belong to a commit) up to parents and do a truncated revision walk. The walk is truncated because it does not produce a revision for every change in the original pathspec, but rather only for active paths. More specifically, consider a priority queue of commits sorted by generation number. First, enqueue the set of boundary commits with all paths in the original spec marked as interesting. Then, while the queue is not empty, do the following: 1. Pop an element, say, 'c', off of the queue, making sure that 'c' isn't reachable by anything in the '--not' set. 2. For each parent 'p' (with index 'parent_i') of 'c', do the following: a. Compute the diff between 'c' and 'p'. b. Pass any active paths that are TREESAME from 'c' to 'p'. c. If 'p' has any active paths, push it onto the queue. 3. Any path that remains active on 'c' is associated to that commit. This ends up being equivalent to doing something like 'git log -1 -- $path' for each path simultaneously. But, it allows us to go much faster than the original implementation by limiting the number of diffs we compute, since we can avoid parts of history that would have been considered by the revision walk in the original implementation, but are known to be uninteresting to us because we have already marked all paths in that area to be inactive. To avoid computing many first-parent diffs, add another trick on top of this and check if all paths active in 'c' are DEFINITELY NOT in c's Bloom filter. Since the commit-graph only stores first-parent diffs in the Bloom filters, we can only apply this trick to first-parent diffs. Comparing the performance of this new algorithm shows about a 2.5x improvement on git.git: Benchmark 1: master no bloom Time (mean ± σ): 2.868 s ± 0.023 s [User: 2.811 s, System: 0.051 s] Range (min … max): 2.847 s … 2.926 s 10 runs Benchmark 2: master with bloom Time (mean ± σ): 949.9 ms ± 15.2 ms [User: 907.6 ms, System: 39.5 ms] Range (min … max): 933.3 ms … 971.2 ms 10 runs Benchmark 3: HEAD no bloom Time (mean ± σ): 782.0 ms ± 6.3 ms [User: 740.7 ms, System: 39.2 ms] Range (min … max): 776.4 ms … 798.2 ms 10 runs Benchmark 4: HEAD with bloom Time (mean ± σ): 307.1 ms ± 1.7 ms [User: 276.4 ms, System: 29.9 ms] Range (min … max): 303.7 ms … 309.5 ms 10 runs Summary HEAD with bloom ran 2.55 ± 0.02 times faster than HEAD no bloom 3.09 ± 0.05 times faster than master with bloom 9.34 ± 0.09 times faster than master no bloom In short, the existing implementation is comparably fast *with* Bloom filters as the new implementation is *without* Bloom filters. So, most repositories should get a dramatic speed-up by just deploying this (even without computing Bloom filters), and all repositories should get faster still when computing Bloom filters. When comparing a more extreme example of `git last-modified -- COPYING t`, the difference is even 5 times better: Benchmark 1: master Time (mean ± σ): 4.372 s ± 0.057 s [User: 4.286 s, System: 0.062 s] Range (min … max): 4.308 s … 4.509 s 10 runs Benchmark 2: HEAD Time (mean ± σ): 826.3 ms ± 22.3 ms [User: 784.1 ms, System: 39.2 ms] Range (min … max): 810.6 ms … 881.2 ms 10 runs Summary HEAD ran 5.29 ± 0.16 times faster than master As an added benefit, results are more consistent now. For example implementation in 'master' gives: $ git log --max-count=1 --format=%H -- pkt-line.h 15df15fe07ef66b51302bb77e393f3c5502629de $ git last-modified -- pkt-line.h 15df15fe07ef66b51302bb77e393f3c5502629de pkt-line.h $ git last-modified | grep pkt-line.h 5b49c1af03e600c286f63d9d9c9fb01403230b9f pkt-line.h With the changes in this patch the results of git-last-modified(1) always match those of `git log --max-count=1`. One thing to note though, the results might be outputted in a different order than before. This is not considerd to be an issue because nowhere is documented the order is guaranteed. Based-on-patches-by: Derrick Stolee <stolee@gmail.com> Based-on-patches-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Toon Claes <toon@iotcl.com> Acked-by: Taylor Blau <me@ttaylorr.com> [jc: tweaked use of xcalloc() to unbreak coccicheck] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-11-03Merge branch 'rs/merge-base-optim'Junio C Hamano1-0/+101
The code to walk revision graph to compute merge base has been optimized. * rs/merge-base-optim: commit-reach: avoid commit_list_insert_by_date()
2025-11-03Merge branch 'jk/diff-patch-dry-run-cleanup'Junio C Hamano1-0/+10
Finishing touches to fixes to the recent regression in "git diff -w --quiet" and anything that needs to internally generate patch to see if it turns empty. * jk/diff-patch-dry-run-cleanup: diff: simplify run_external_diff() quiet logic diff: drop dry-run redirection to /dev/null diff: replace diff_options.dry_run flag with NULL file diff: drop save/restore of color_moved in dry-run mode diff: send external diff output to diff_options.file
2025-11-03Merge branch 'ps/maintenance-geometric'Junio C Hamano1-0/+245
"git maintenance" command learns the "geometric" strategy where it avoids doing maintenance tasks that rebuilds everything from scratch. * ps/maintenance-geometric: t7900: fix a flaky test due to git-repack always regenerating MIDX builtin/maintenance: introduce "geometric" strategy builtin/maintenance: make "gc" strategy accessible builtin/maintenance: extend "maintenance.strategy" to manual maintenance builtin/maintenance: run maintenance tasks depending on type builtin/maintenance: improve readability of strategies builtin/maintenance: don't silently ignore invalid strategy builtin/maintenance: make the geometric factor configurable builtin/maintenance: introduce "geometric-repack" task builtin/gc: make `too_many_loose_objects()` reusable without GC config builtin/gc: remove global `repack` variable
2025-11-03Merge branch 'jk/match-pathname-fix'Junio C Hamano1-0/+11
The wildmatch code had a corner case bug that mistakenly makes "foo**/bar" match with "foobar", which has been corrected. * jk/match-pathname-fix: match_pathname(): give fnmatch one char of prefix context match_pathname(): reorder prefix-match check
2025-11-03Merge branch 'rs/add-patch-quit'Junio C Hamano1-0/+11
The 'q'(uit) command in "git add -p" has been improved to quit without doing any meaningless work before leaving, and giving EOF (typically control-D) to the prompt is made to behave the same way. * rs/add-patch-quit: add-patch: quit on EOF add-patch: quit without skipping undecided hunks
2025-10-30Merge branch 'ly/diff-name-only-with-diff-from-content'Junio C Hamano1-0/+37
Regression fixes for a topic that has already been merged. * ly/diff-name-only-with-diff-from-content: diff: stop output garbled message in dry run mode
2025-10-30Merge branch 'ps/remove-packfile-store-get-packs'Junio C Hamano2-2/+3
Two slightly different ways to get at "all the packfiles" in API has been cleaned up. * ps/remove-packfile-store-get-packs: packfile: rename `packfile_store_get_all_packs()` packfile: introduce macro to iterate through packs packfile: drop `packfile_store_get_packs()` builtin/grep: simplify how we preload packs builtin/gc: convert to use `packfile_store_get_all_packs()` object-name: convert to use `packfile_store_get_all_packs()`
2025-10-30Merge branch 'ps/symlink-symref-deprecation'Junio C Hamano1-3/+23
"Symlink symref" has been added to the list of things that will disappear at Git 3.0 boundary. * ps/symlink-symref-deprecation: refs/files: deprecate writing symrefs as symbolic links
2025-10-30Merge branch 'ey/commit-graph-changed-paths-config'Junio C Hamano1-0/+44
A new configuration variable commitGraph.changedPaths allows to turn "--changed-paths" on by default for "git commit-graph". * ey/commit-graph-changed-paths-config: commit-graph: add new config for changed-paths & recommend it in scalar
2025-10-30fast-import: mark strings for translationChristian Couder1-10/+10
Some error or warning messages in "builtin/fast-import.c" are marked for translation, but many are not. To be more consistent and provide a better experience to people using a translated version, let's mark all the remaining error or warning messages for translation. While at it, let's make the following small changes: - replace "GIT" or "git" in a few error messages to just "Git", - replace "Expected from command, got %s" to "expected 'from' command, got '%s'", which makes it clearer that "from" is a command and should not be translated, - downcase error and warning messages that start with an uppercase, - fix test cases in "t9300-fast-import.sh" that broke because an error or warning message was downcased, - split error and warning messages that are too long, - adjust the indentation of some arguments of the error functions. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-29test-tool: fix leak in delete-gpgsig commandJeff King1-3/+4
We read the input into a strbuf, so we must free it. Without this, t1016 complains in SANITIZE=leak mode. The bug was introduced in 7673ecd2dc (t1016-compatObjectFormat: add tests to verify the conversion between objects, 2023-10-01). But nobody seems to have noticed, probably because CI did not run these tests until the fix in 6cd8369ef3 (t/lib-gpg: call prepare_gnupghome() in GPG2 prereq, 2024-07-03). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-29doc: document backslash in gitignore patternsJeff King1-0/+2
Because gitignore patterns are passed to fnmatch, the handling of backslashes is the same as it is there: it can be used to escape metacharacters. We do reference fnmatch(3) for more details, but it may be friendlier to point out this implication explicitly (especially for people who want to know about backslash handling and search the documentation for that word). There are also two cases that I've seen some other backslash-escaping systems handle differently, so let's describe those: 1. A backslash before any character treats that character literally, even if it's not otherwise a meta-character. As opposed to including the backslash itself (like "foo\bar" in shell expands to "foo\bar") or forbidding it ("foo\zar" is required to produce a diagnostic in C). 2. A backslash at the end of the string is an invalid pattern (and not a literal backslash). This second one in particular was a point of confusion between our implementation and the one in JGit. Our wildmatch behavior matches what POSIX specifies for fnmatch, so the code and documentation are in line. But let's add a test to cover this case. Note that the behavior here differs between wildmatch itself (which is what gitignore will use) and pathspec matching (which will only turn to wildmatch if a literal match fails). So we match "foo\" to "foo\" in pathspecs, but not via gitignore. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-28t1016-compatObjectFormat: really freeze time for reproduciblityEric W. Biederman2-1/+7
The strategy in t1016-compatObjectFormat is to build two trees with identical commits, one tree encoded in sha1 the other tree encoded in sha256 and to use the compatibility code to test and see if the two trees are identical. GPG signatures include the current time as part of the signature. To make gpg deterministic I forced the use of gpg --faked-system-time. Unfortunately I did not look closely enough. By default gpg still allows time to move forward with --faked-system-time. So in those rare instances when the system is heavily loaded and gpg runs slower than other times, signatures over the exact same data differ due to timestamps with a minuscule difference. Reading through the gpg documentation with a close eye, time can be frozen by including an exclamation point at the end of the argument to --faked-system-time. Add the exclamation point so gpg really runs with a fixed notion of time, resulting in the exact same data having identical gpg signatures. That is enough that I can run "t1016-compatObjectFormat.sh --stress" and I don't see any failures. It is possible a future change to gpg will make replay protection more robust and not provide a way to allow two separate runs of gpg to produce exactly the same signature for exactly the same data. If that happens a deeper comparison of the two repositories will need to be performed. A comparison that simply verifies the signatures and compares the data for equality. For now that is a lot of work for no gain so I am just documenting the possibility. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-28bisect: update usage and docs to match each otherRuoyu Zhong1-1/+0
Update the usage string of `git bisect` and documentation to match each other. While at it, also: 1. Move the synopsis of `git bisect` subcommands to the synopsis section, so that the test `t0450-txt-doc-vs-help.sh` can pass. 2. Document the `git bisect next` subcommand, which exists in the code but is missing from the documentation. See also: [1]. [1]: https://lore.kernel.org/git/3DA38465-7636-4EEF-B074-53E4628F5355@gmail.com/ Suggested-by: Ben Knoble <ben.knoble@gmail.com> Signed-off-by: Ruoyu Zhong <zhongruoyu@outlook.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-28Merge branch 'cc/fast-import-strip-signed-tags'Junio C Hamano4-8/+145
"git fast-import" is taught to handle signed tags, just like it recently learned to handle signed commits, in different ways. * cc/fast-import-strip-signed-tags: fast-import: add '--signed-tags=<mode>' option fast-export: handle all kinds of tag signatures t9350: properly count annotated tags lib-gpg: allow tests with GPGSM or GPGSSH prereq first doc: git-tag: stop focusing on GPG signed tags
2025-10-28Merge branch 'ds/sparse-checkout-clean'Junio C Hamano1-0/+175
"git sparse-checkout" subcommand learned a new "clean" action to prune otherwise unused working-tree files that are outside the areas of interest. * ds/sparse-checkout-clean: sparse-index: improve advice message instructions t: expand tests around sparse merges and clean sparse-index: point users to new 'clean' action sparse-checkout: add --verbose option to 'clean' dir: add generic "walk all files" helper sparse-checkout: match some 'clean' behavior sparse-checkout: add basics of 'clean' command sparse-checkout: remove use of the_repository
2025-10-27t7900: fix a flaky test due to git-repack always regenerating MIDXPatrick Steinhardt1-2/+2
When a supposedly no-op "git repack" runs across a second boundary, because the command always touches the MIDX file and updates its timestamp, "ls -l $GIT_DIR/objects/pack/" before and after the operation can change, which causes such a test to fail. Only compare the *.pack files in the directory before and after the operation to work around this flakyness. Arguably, git-repack(1) should learn to not rewrite the MIDX in case we know it is already up-to-date. But this is not a new problem introduced via the new geometric maintenance task, so for now it should be good enough to paper over the issue. Signed-off-by: Patrick Steinhardt <ps@pks.im> [jc: taken from diff to v4 from v3 that was already merged to 'next'] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-26Merge branch 'so/t2401-use-test-path-helpers' into maint-2.51Junio C Hamano1-17/+17
Test modernization. * so/t2401-use-test-path-helpers: t2401: update path checks using test_path helpers
2025-10-26Merge branch 'ps/t7528-ssh-agent-uds-workaround' into maint-2.51Junio C Hamano1-1/+1
Recent OpenSSH creates the Unix domain socket to communicate with ssh-agent under $HOME instead of /tmp, which causes our test to fail doe to overly long pathname in our test environment, which has been worked around by using "ssh-agent -T". * ps/t7528-ssh-agent-uds-workaround: t7528: work around ETOOMANY in OpenSSH 10.1 and newer
2025-10-26Merge branch 'jk/status-z-short-fix' into maint-2.51Junio C Hamano1-0/+11
The "--short" option of "git status" that meant output for humans and "-z" option to show NUL delimited output format did not mix well, and colored some but not all things. The command has been updated to color all elements consistently in such a case. * jk/status-z-short-fix: status: make coloring of "-z --short" consistent
2025-10-26Merge branch 'jk/diff-no-index-with-pathspec-fix' into maint-2.51Junio C Hamano1-0/+16
An earlier addition to "git diff --no-index A B" to limit the output with pathspec after the two directories misbehaved when these directories were given with a trailing slash, which has been corrected. * jk/diff-no-index-with-pathspec-fix: diff --no-index: fix logic for paths ending in '/'
2025-10-26Merge branch 'jk/diff-from-contents-fix' into maint-2.51Junio C Hamano1-0/+4
Recently we attempted to improve "git diff -w" and friends to handle cases where patch output would be suppressed, but it introduced a bug that emits unnecessary output, which has been corrected. * jk/diff-from-contents-fix: diff: restore redirection to /dev/null for diff_from_contents
2025-10-26add-patch: quit on EOFRené Scharfe1-0/+11
If we reach the end of the input, e.g. because the user pressed ctrl-D on Linux, there is no point in showing any more prompts, as we won't get any reply. Do the same as option 'q' would: Quit. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-26match_pathname(): give fnmatch one char of prefix contextJeff King1-0/+11
In match_pathname(), which we use for matching .gitignore and .gitattribute patterns, we are comparing paths with fnmatch patterns (actually our extended wildmatch, which will be important). There's an extra optimization there: we pre-compute the number of non-wildcard characters at the beginning of the pattern and do an fspathncmp() on that prefix. That lets us avoid fnmatch entirely on patterns without wildcards, and shrinks the amount of work we hand off to fnmatch. For a pattern like "foo*.txt" and a path "foobar.txt", we'd cut away the matching "foo" prefix and just pass "*.txt" and "bar.txt" to fnmatch(). But this misses a subtle corner case. In fnmatch(), we'll think "bar.txt" is the start of the path, but it's not. This doesn't matter for the pattern above, but consider the wildmatch pattern "foo**/bar" and the path "foobar". These two should not match, because there is no file named "bar", and the "**" applies only to the containing directory name. But after removing the "foo" prefix, fnmatch will get "**/bar" and "bar", which it does consider a match, because "**/" can match zero directories. We can solve this by giving fnmatch a bit more context. As long as it has one byte of the matched prefix, then it will know that "bar" is not the start of the path. In this example it would get "o**/bar" and "obar", and realize that they cannot match. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24Merge branch 'ps/t7528-ssh-agent-uds-workaround'Junio C Hamano1-1/+1
Recent OpenSSH creates the Unix domain socket to communicate with ssh-agent under $HOME instead of /tmp, which causes our test to fail doe to overly long pathname in our test environment, which has been worked around by using "ssh-agent -T". * ps/t7528-ssh-agent-uds-workaround: t7528: work around ETOOMANY in OpenSSH 10.1 and newer
2025-10-24Merge branch 'rs/add-patch-document-p-for-pager'Junio C Hamano1-22/+22
Show 'P'ipe command in "git add -p". * rs/add-patch-document-p-for-pager: add-patch: fully document option P
2025-10-24Merge branch 'jc/t1016-setup-fix'Junio C Hamano1-1/+1
GPG signing test set-up has been broken for a year, which has been corrected. * jc/t1016-setup-fix: t1016: make sure to use specified GPG
2025-10-24Merge branch 'jk/status-z-short-fix'Junio C Hamano1-0/+11
The "--short" option of "git status" that meant output for humans and "-z" option to show NUL delimited output format did not mix well, and colored some but not all things. The command has been updated to color all elements consistently in such a case. * jk/status-z-short-fix: status: make coloring of "-z --short" consistent
2025-10-24Merge branch 'js/t7500-pwd-windows-fix'Junio C Hamano1-5/+14
Test fix. * js/t7500-pwd-windows-fix: t7500: fix tests with absolute path following ":(optional)" on Windows
2025-10-24builtin/maintenance: introduce "geometric" strategyPatrick Steinhardt1-1/+19
We have two different repacking strategies in Git: - The "gc" strategy uses git-gc(1). - The "incremental" strategy uses multi-pack indices and `git multi-pack-index repack` to merge together smaller packfiles as determined by a specific batch size. The former strategy is our old and trusted default, whereas the latter has historically been used for our scheduled maintenance. But both strategies have their shortcomings: - The "gc" strategy performs regular all-into-one repacks. Furthermore it is rather inflexible, as it is not easily possible for a user to enable or disable specific subtasks. - The "incremental" strategy is not a full replacement for the "gc" strategy as it doesn't know to prune stale data. So today, we don't have a strategy that is well-suited for large repos while being a full replacement for the "gc" strategy. Introduce a new "geometric" strategy that aims to fill this gap. This strategy invokes all the usual cleanup tasks that git-gc(1) does like pruning reflogs and rerere caches as well as stale worktrees. But where it differs from both the "gc" and "incremental" strategy is that it uses our geometric repacking infrastructure exposed by git-repack(1) to repack packfiles. The advantage of geometric repacking is that we only need to perform an all-into-one repack when the object count in a repo has grown significantly. One downside of this strategy is that pruning of unreferenced objects is not going to happen regularly anymore. Every geometric repack knows to soak up all loose objects regardless of their reachability, and merging two or more packs doesn't consider reachability, either. Consequently, the number of unreachable objects will grow over time. This is remedied by doing an all-into-one repack instead of a geometric repack whenever we determine that the geometric repack would end up merging all packfiles anyway. This all-into-one repack then performs our usual reachability checks and writes unreachable objects into a cruft pack. As cruft packs won't ever be merged during geometric repacks we can thus phase out these objects over time. Of course, this still means that we retain unreachable objects for far longer than with the "gc" strategy. But the maintenance strategy is intended especially for large repositories, where the basic assumption is that the set of unreachable objects will be significantly dwarfed by the number of reachable objects. If this assumption is ever proven to be too disadvantageous we could for example introduce a time-based strategy: if the largest packfile has not been touched for longer than $T, we perform an all-into-one repack. But for now, such a mechanism is deferred into the future as it is not clear yet whether it is needed in the first place. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24builtin/maintenance: make "gc" strategy accessiblePatrick Steinhardt1-1/+13
While the user can pick the "incremental" maintenance strategy, it is not possible to explicitly use the "gc" strategy. This has two downsides: - It is impossible to use the default "gc" strategy for a specific repository when the strategy was globally set to a different strategy. - It is not possible to use git-gc(1) for scheduled maintenance. Address these issues by making making the "gc" strategy configurable. Furthermore, extend the strategy so that git-gc(1) runs for both manual and scheduled maintenance. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24builtin/maintenance: extend "maintenance.strategy" to manual maintenancePatrick Steinhardt1-0/+40
The "maintenance.strategy" configuration allows users to configure how Git is supposed to perform repository maintenance. The idea is that we provide a set of high-level strategies that may be useful in different contexts, like for example when handling a large monorepo. Furthermore, the strategy can be tweaked by the user by overriding specific tasks. In its current form though, the strategy only applies to scheduled maintenance. This creates something of a gap, as scheduled and manual maintenance will now use _different_ strategies as the latter would continue to use git-gc(1) by default. This makes the strategies way less useful than they could be on the one hand. But even more importantly, the two different strategies might clash with one another, where one of the strategies performs maintenance in such a way that it discards benefits from the other strategy. So ideally, it should be possible to pick one strategy that then applies globally to all the different ways that we perform maintenance. This doesn't necessarily mean that the strategy always does the _same_ thing for every maintenance type. But it means that the strategy can configure the different types to work in tandem with each other. Change the meaning of "maintenance.strategy" accordingly so that the strategy is applied to both types, manual and scheduled. As preceding commits have introduced logic to run maintenance tasks depending on this type we can tweak strategies so that they perform those tasks depending on the context. Note that this raises the question of backwards compatibility: when the user has configured the "incremental" strategy we would have ignored that strategy beforehand. Instead, repository maintenance would have continued to use git-gc(1) by default. But luckily, we can match that behaviour by: - Keeping all current tasks of the incremental strategy as `MAINTENANCE_TYPE_SCHEDULED`. This ensures that those tasks will not run during manual maintenance. - Configuring the "gc" task so that it is invoked during manual maintenance. Like this, the user shouldn't observe any difference in behaviour. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24builtin/maintenance: don't silently ignore invalid strategyPatrick Steinhardt1-0/+5
When parsing maintenance strategies we completely ignore the user-configured value in case it is unknown to us. This makes it basically undiscoverable to the user that scheduled maintenance is devolving into a no-op. Change this to instead die when seeing an unknown maintenance strategy. While at it, pull out the parsing logic into a separate function so that we can reuse it in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24builtin/maintenance: make the geometric factor configurablePatrick Steinhardt1-0/+32
The geometric repacking task uses a factor of two for its geometric sequence, meaning that each next pack must contain at least twice as many objects as the next-smaller one. In some cases it may be helpful to configure this factor though to reduce the number of packfile merges even further, e.g. in very big repositories. But while git-repack(1) itself supports doing this, the maintenance task does not give us a way to tune it. Introduce a new "maintenance.geometric-repack.splitFactor" configuration to plug this gap. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24builtin/maintenance: introduce "geometric-repack" taskPatrick Steinhardt1-0/+138
Introduce a new "geometric-repack" task. This task uses our geometric repack infrastructure as provided by git-repack(1) itself, which is a strategy that especially hosting providers tend to use to amortize the costs of repacking objects. There is one issue though with geometric repacks, namely that they unconditionally pack all loose objects, regardless of whether or not they are reachable. This is done because it means that we can completely skip the reachability step, which significantly speeds up the operation. But it has the big downside that we are unable to expire objects over time. To address this issue we thus use a split strategy in this new task: whenever a geometric repack would merge together all packs, we instead do an all-into-one repack. By default, these all-into-one repacks have cruft packs enabled, so unreachable objects would now be written into their own pack. Consequently, they won't be soaked up during geometric repacking anymore and can be expired with the next full repack, assuming that their expiry date has surpassed. Signed-off-by: Patrick Steinhardt <ps@pks.im> Acked-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24diff: send external diff output to diff_options.fileJeff King1-0/+10
Diff output usually goes to the process stdout, but it can be redirected with the "--output" option. We store this in the "file" pointer of diff_options, and all of the diff code should write there instead of to stdout. But there's one spot we missed: running an external diff cmd. We don't redirect its output at all, so it just defaults to the stdout of the parent process. We should instead point its stdout at our output file. There are a few caveats to watch out for when doing so: - The stdout field takes a descriptor, not a FILE pointer. We can pull out the descriptor with fileno(). - The run-command API always closes the stdout descriptor we pass to it. So we must duplicate it (otherwise we break the FILE pointer, since it now points to a closed descriptor). - We don't need to worry about closing our dup'd descriptor, since the point is that run-command will do it for us (even in the case of an error). But we do need to make sure we skip the dup() if we set no_stdout (because then run-command will not look at it at all). - When the output is going to stdout, it would not be wrong to dup() the descriptor, but we don't need to. We can skip that extra work with a simple pointer comparison. - It seems like you'd need to fflush() the descriptor before handing off a copy to the child process to prevent out-of-order writes. But that was true even before this patch! It works because run-command always calls fflush(NULL) before running the child. The new test shows the breakage (and fix). The need for duplicating the descriptor doesn't need a new test; that is covered by the later test "GIT_EXTERNAL_DIFF with more than one changed files". Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24commit-reach: avoid commit_list_insert_by_date()René Scharfe1-0/+101
Building a list using commit_list_insert_by_date() has quadratic worst case complexity. Avoid it by just appending in the loop and sorting at the end. The number of merge bases is usually small, so don't expect speedups in normal repositories. It has no limit, though. The added perf test shows a nice improvement when dealing with 16384 merge bases: Test v2.51.1 HEAD ----------------------------------------------------------------- 6010.2: git merge-base 0.55(0.54+0.00) 0.03(0.02+0.00) -94.5% Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-24Merge branch 'jk/diff-from-contents-fix'Junio C Hamano1-0/+4
Recently we attempted to improve "git diff -w" and friends to handle cases where patch output would be suppressed, but it introduced a bug that emits unnecessary output, which has been corrected. * jk/diff-from-contents-fix: diff: restore redirection to /dev/null for diff_from_contents
2025-10-23t7528: work around ETOOMANY in OpenSSH 10.1 and newerPatrick Steinhardt1-1/+1
In t7528 we spawn an SSH agent to verify that we can sign a commit via it. This test has started to fail on some machines: +++ ssh-agent unix_listener_tmp: path "/home/pks/Development/git/build/test-output/trash directory.t7528-signed-commit-ssh/.ssh/agent/s.UTulegefEg.agent.UrPHumMXPq" too long for Unix domain socket main: Couldn't prepare agent socket As it turns out this is caused by a change in OpenSSH 10.1 [1]: * ssh-agent(1), sshd(8): move agent listener sockets from /tmp to under ~/.ssh/agent for both ssh-agent(1) and forwarded sockets in sshd(8). Instead of creating the socket in "/tmp", OpenSSH now creates the socket in our home directory. And as the home directory gets modified to be located in our test output directory we end up with paths that are somewhat long. But Linux has a rather short limit of 108 characters for socket paths, and other systems have even lower limits, so it is very easy now to exceed the limit and run into the above error. Work around the issue by using `ssh-agent -T`, which instructs it to use the old behaviour and create the socket in "/tmp" again. This switch has only been introduced with 10.1 though, so for older versions we have to fall back to not using it. That's fine though, as older versions know to put the socket into "/tmp" already. An alternative approach would be to abbreviate the socket name itself so that we create it as e.g. "sshsock" in the trash directory. But taking the above example we'd still end up with a path that is 91 characters long. So we wouldn't really have a lot of headroom, and it is quite likely that some developers would see the issue on their machines. [1]: https://www.openssh.com/txt/release-10.1 Reported-by: Xi Ruoyao <xry111@xry111.site> Suggested-by: brian m. carlson <sandals@crustytoothpaste.net> Helped-by: Jeff King <peff@peff.net> Helped-by: Lauri Tirkkonen <lauri@hacktheplanet.fi> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-23diff: stop output garbled message in dry run modeLidong Yan1-0/+37
Earlier, b55e6d36 (diff: ensure consistent diff behavior with ignore options, 2025-08-08) introduced "dry-run" mode to the diff machinery so that content-based diff filtering (like ignoring space changes or those that match -I<regex>) can first try to produce a patch without emitting any output to see if under the given diff filtering condition we would get any output lines, and a new helper function diff_flush_patch_quietly() was introduced to use the mode to see an individual filepair needs to be shown. However, the solution was not complete. When files are deleted, file modes change, or there are unmerged entries in the index, dry-run mode still produces output because we overlooked these conditions, and as a result, dry-run mode was not quiet. To fix this, return early in emit_diff_symbol_from_struct() if we are in dry-run mode. This function will be called by all the emit functions to output the results. Returning early can avoid diff output when files are deleted or file modes are changed. Stop print message in dry-run mode if we have unmerged entries in index. Discard output of external diff tool in dry-run mode. Signed-off-by: Lidong Yan <yldhome2d2@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-22Merge branch 'jk/diff-from-contents-fix' into ↵Junio C Hamano1-0/+4
ly/diff-name-only-with-diff-from-content * jk/diff-from-contents-fix: diff: restore redirection to /dev/null for diff_from_contents
2025-10-22Merge branch 'so/t2401-use-test-path-helpers'Junio C Hamano1-17/+17
Test modernization. * so/t2401-use-test-path-helpers: t2401: update path checks using test_path helpers
2025-10-22Merge branch 'bc/sha1-256-interop-01'Junio C Hamano5-7/+116
The beginning of SHA1-SHA256 interoperability work. * bc/sha1-256-interop-01: t1010: use BROKEN_OBJECTS prerequisite t: allow specifying compatibility hash fsck: consider gpgsig headers expected in tags rev-parse: allow printing compatibility hash docs: add documentation for loose objects docs: improve ambiguous areas of pack format documentation docs: reflect actual double signature for tags docs: update offset order for pack index v3 docs: update pack index v3 format
2025-10-22commit-graph: add new config for changed-paths & recommend it in scalarEmily Yang1-0/+44
The changed-path Bloom filters feature has proven stable and reliable over several years of use, delivering significant performance improvement for file history computation in large monorepos. Currently a user can opt-in to writing the changed-path Bloom filters using the "--changed-paths" option to "git commit-graph write". The filters will be persisted until the user drops the filters using the "--no-changed-paths" option. For this functionality, refer to 0087a87ba8 (commit-graph: persist existence of changed-paths, 2020-07-01). Large monorepos using Git's background maintenance to build and update commit-graph files could use an easy switch to enable this feature without a foreground computation. In this commit, we're proposing a new config option "commitGraph.changedPaths": * If "true", "git commit-graph write" will write Bloom filters, equivalent to passing "--changed-paths"; * If "false" or "unset", Bloom filters will be written during "git commit-graph write" only if the filters already exist in the current commit-graph file. This matches the default behaviour of "git commit-graph write" without any "--[no-]changed-paths" option. Note "false" can disable a previous "true" config value but doesn't imply "--no-changed-paths". This config will always respect the precedence of command line option "--[no-]changed-paths". We also set this new config as optional recommended config in scalar to turn on this feature for large repos. Helped-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Emily Yang <emilyyang.git@gmail.com> Acked-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-22Merge branch 'jt/repo-structure' into ps/ref-peeled-tagsJunio C Hamano2-0/+130
* jt/repo-structure: builtin/repo: add progress meter for structure stats builtin/repo: add keyvalue and nul format for structure stats builtin/repo: add object counts in structure output builtin/repo: introduce structure subcommand ref-filter: export ref_kind_from_refname() ref-filter: allow NULL filter pattern builtin/repo: rename repo_info() to cmd_repo_info()
2025-10-21builtin/repo: add progress meter for structure statsJustin Tobler1-0/+20
When using the structure subcommand for git-repo(1), evaluating a repository may take some time depending on its shape. Add a progress meter to provide feedback to the user about what is happening. The progress meter is enabled by default when the command is executed from a tty. It can also be explicitly enabled/disabled via the --[no-]progress option. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-21builtin/repo: add keyvalue and nul format for structure statsJustin Tobler1-0/+33
All repository structure stats are outputted in a human-friendly table form. This format is not suitable for machine parsing. Add a --format option that supports three output modes: `table`, `keyvalue`, and `nul`. The `table` mode is the default format and prints the same table output as before. With the `keyvalue` mode, each line of output contains a key-value pair of a repository stat. The '=' character is used to delimit between keys and values. The `nul` mode is similar to `keyvalue`, but key-values are delimited by a NUL character instead of a newline. Also, instead of a '=' character to delimit between keys and values, a newline character is used. This allows stat values to support special characters without having to cquote them. These two new modes provides output that is more machine-friendly. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-21builtin/repo: add object counts in structure outputJustin Tobler1-2/+17
The amount of objects in a repository can provide insight regarding its shape. To surface this information, use the path-walk API to count the number of reachable objects in the repository by object type. All regular references are used to determine the reachable set of objects. The object counts are appended to the same table containing the reference information. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-21builtin/repo: introduce structure subcommandJustin Tobler2-0/+62
The structure of a repository's history can have huge impacts on the performance and health of the repository itself. Currently, Git lacks a means to surface repository metrics regarding its structure/shape via a single command. Acquiring this information requires users to be familiar with the relevant data points and the various Git commands required to surface them. To fill this gap, supplemental tools such as git-sizer(1) have been developed. To allow users to more readily identify repository structure related information, introduce the "structure" subcommand in git-repo(1). The goal of this subcommand is to eventually provide similar functionality to git-sizer(1), but natively in Git. The initial version of this command only iterates through all references in the repository and tracks the count of branches, tags, remote refs, and other reference types. The corresponding information is displayed in a human-friendly table formatted in a very similar manner to git-sizer(1). The width of each table column is adjusted automatically to satisfy the requirements of the widest row contained. Subsequent commits will surface additional relevant data points to output and also provide other more machine-friendly output formats. Based-on-patch-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-21add-patch: fully document option PRené Scharfe1-22/+22
Show option P in the prompt and explain it properly on a dedicated line in online help and documentation. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-21Merge branch 'tb/incremental-midx-part-3.1' into ps/maintenance-geometricJunio C Hamano2-2/+2
* tb/incremental-midx-part-3.1: (64 commits) builtin/repack.c: clean up unused `#include`s repack: move `write_cruft_pack()` out of the builtin repack: move `write_filtered_pack()` out of the builtin repack: move `pack_kept_objects` to `struct pack_objects_args` repack: move `finish_pack_objects_cmd()` out of the builtin builtin/repack.c: pass `write_pack_opts` to `finish_pack_objects_cmd()` repack: extract `write_pack_opts_is_local()` repack: move `find_pack_prefix()` out of the builtin builtin/repack.c: use `write_pack_opts` within `write_cruft_pack()` builtin/repack.c: introduce `struct write_pack_opts` repack: 'write_midx_included_packs' API from the builtin builtin/repack.c: inline packs within `write_midx_included_packs()` builtin/repack.c: pass `repack_write_midx_opts` to `midx_included_packs` builtin/repack.c: inline `remove_redundant_bitmaps()` builtin/repack.c: reorder `remove_redundant_bitmaps()` repack: keep track of MIDX pack names using existing_packs builtin/repack.c: use a string_list for 'midx_pack_names' builtin/repack.c: extract opts struct for 'write_midx_included_packs()' builtin/repack.c: remove ref snapshotting from builtin repack: remove pack_geometry API from the builtin ...
2025-10-20t7500: fix tests with absolute path following ":(optional)" on WindowsJohannes Sixt1-5/+14
On Windows, the MSYS layer translates absolute path names generated by a shell script from the POSIX style /c/dir/file to the Windows style C:/dir/file form that is understood by git.exe. This happens only when the absolute path stands on its own as a program argument or a value of an environment variable. The earlier commits 749d6d166d (config: values of pathname type can be prefixed with :(optional), 2025-09-28) and ccfcaf399f (parseopt: values of pathname type can be prefixed with :(optional), 2025-09-28) added test cases where ":(optional)" is inserted before an absolute path. $PWD is used to construct the absolute paths, which gives the POSIX form, and the result is ":(optional)/c/dir/template". Such command line arguments are no longer recognized as absolute paths and do not undergo translation. Existing test cases that expect that the specified file does not exist are not incorrect (after all, git.exe will not find /c/dir/template). Yet, they are conceptually incorrect. That the use of $PWD is erroneous is revealed by a test case that expects that the optional file exists. Since no such test case is present, add one. Use "$(pwd)" to generate the absolute paths, so that the command line arguments become ":(optional)C:/dir/template". Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-17status: make coloring of "-z --short" consistentJeff King1-0/+11
When running "git status -z --short", the marker on modified index entries (e.g., "M") is colorized, but the "??" marker for untracked entries is not. Let's fix the "??" entries to show color here. At first glance you might think that neither should be colorized, as usually one would use "-z" to get machine-readable output. But this is a tricky and unusual case. We have two output formats, "--short" and "--porcelain" which are substantially similar, but differ in that "--short" is for humans who want something short and "--porcelain" is for machines. And "-z" by itself, without any other output option, does default to "--porcelain", so "git status -z" will not colorize anything. But if you explicitly ask for "-z" and "--short" together, then that is asking for the human-readable output, but separated by NULs. This is unlikely to be useful directly, but could for example be used if the output will be shown to a human outside of the terminal. At any rate, the current behavior is clearly wrong (since we colorize some things but not others), and I think colorizing everything is the least-surprising thing we can do here. Reported-by: Langbart <Langbart@protonmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-17Merge branch 'jk/diff-no-index-with-pathspec-fix'Junio C Hamano1-0/+16
An earlier addition to "git diff --no-index A B" to limit the output with pathspec after the two directories misbehaved when these directories were given with a trailing slash, which has been corrected. * jk/diff-no-index-with-pathspec-fix: diff --no-index: fix logic for paths ending in '/'
2025-10-17Merge branch 'rs/add-patch-options-fix'Junio C Hamano1-15/+61
The code in "git add -p" and friends to iterate over hunks was riddled with bugs, which has been corrected. * rs/add-patch-options-fix: add-patch: reset "permitted" at loop start add-patch: let options a and d roll over like y and n add-patch: let options k and K roll over like j and J add-patch: let options y, n, j, and e roll over to next undecided add-patch: document that option J rolls over add-patch: improve help for options j, J, k, and K
2025-10-17diff: restore redirection to /dev/null for diff_from_contentsJeff King1-0/+4
In --quiet mode, since we produce only an exit code for "something was changed" and no actual output, we can often get by with just a tree-level diff. However, certain options require us to actually look at the file contents (e.g., if we are ignoring whitespace changes). We have a flag "diff_from_contents" for that, and if it is set we call diff_flush() on each path. To avoid producing any output (since we were asked to be --quiet), we traditionally just redirected the output to /dev/null. That changed in b55e6d36eb (diff: ensure consistent diff behavior with ignore options, 2025-08-08), which replaced that with a "dry_run" flag. In theory, with dry_run set, we should produce no output. But it carries a risk of regression: if we forget to respect dry_run in any of the output paths, we'll accidentally produce output. And indeed, there is at least one such regression in that commit, as it covered only the case where we actually call into xdiff, and not creation or deletion diffs, where we manually generate the headers. We even test this case in t4035, but only with diff-tree, which does not show the bug by default because it does not require diff_from_contents. But git-diff does, because it allows external diff programs by default (so we must dig into each diff filepair to decide if it requires running an external diff that may declare two distinct blobs to actually be the same). We should fix all of those code paths to respect dry_run correctly, but in the meantime we can protect ourselves more fully by restoring the redirection to /dev/null. This gives us an extra layer of protection against regressions dues to other code paths we've missed. Though the original issue was reported with "git diff" (and due to its default of --ext-diff), I've used "diff-tree -w" in the new test. It triggers the same issue, but I think the fact that "-w" implies diff_from_contents is a bit more obvious, and fits in with the rest of t4035. Reported-by: Jake Zimmerman <jake@zimmerman.io> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-17Merge branch 'ly/diff-name-only-with-diff-from-content' into ↵Junio C Hamano2-6/+15
jk/diff-from-contents-fix * ly/diff-name-only-with-diff-from-content: diff: ensure consistent diff behavior with ignore options
2025-10-16packfile: introduce macro to iterate through packsPatrick Steinhardt2-2/+3
We have a bunch of different sites that want to iterate through all packs of a given `struct packfile_store`. This pattern is somewhat verbose and repetitive, which makes it somewhat cumbersome. Introduce a new macro `repo_for_each_pack()` that removes some of the boilerplate. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-16Merge branch 'tb/incremental-midx-part-3.1' into ↵Junio C Hamano2-2/+2
ps/remove-packfile-store-get-packs * tb/incremental-midx-part-3.1: (64 commits) builtin/repack.c: clean up unused `#include`s repack: move `write_cruft_pack()` out of the builtin repack: move `write_filtered_pack()` out of the builtin repack: move `pack_kept_objects` to `struct pack_objects_args` repack: move `finish_pack_objects_cmd()` out of the builtin builtin/repack.c: pass `write_pack_opts` to `finish_pack_objects_cmd()` repack: extract `write_pack_opts_is_local()` repack: move `find_pack_prefix()` out of the builtin builtin/repack.c: use `write_pack_opts` within `write_cruft_pack()` builtin/repack.c: introduce `struct write_pack_opts` repack: 'write_midx_included_packs' API from the builtin builtin/repack.c: inline packs within `write_midx_included_packs()` builtin/repack.c: pass `repack_write_midx_opts` to `midx_included_packs` builtin/repack.c: inline `remove_redundant_bitmaps()` builtin/repack.c: reorder `remove_redundant_bitmaps()` repack: keep track of MIDX pack names using existing_packs builtin/repack.c: use a string_list for 'midx_pack_names' builtin/repack.c: extract opts struct for 'write_midx_included_packs()' builtin/repack.c: remove ref snapshotting from builtin repack: remove pack_geometry API from the builtin ...
2025-10-15t2401: update path checks using test_path helpersSolly1-17/+17
Update old-style shell path checks to use the modern test helpers 'test_path_is_file' and 'test_path_is_dir' for improved runtime diagnosis. Signed-off-by: Solly <solobarine@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-15Merge branch 'mh/doc-credential-url-prefix' into maint-2.51Junio C Hamano1-4/+15
Doc update to describe a feature that has already been implemented. * mh/doc-credential-url-prefix: docs/gitcredentials: describe URL prefix matching
2025-10-15Merge branch 'ps/odb-clean-stale-wrappers' into maint-2.51Junio C Hamano1-6/+4
Code clean-up. * ps/odb-clean-stale-wrappers: odb: drop deprecated wrapper functions
2025-10-15Merge branch 'rj/t6137-cygwin-fix' into maint-2.51Junio C Hamano1-6/+6
Test fix for breakage introduced in Git 2.50. * rj/t6137-cygwin-fix: t6137-*.sh: fix test failure on cygwin
2025-10-15Merge branch 'kn/refs-files-case-insensitive' into maint-2.51Junio C Hamano2-1/+166
Deal more gracefully with directory / file conflicts when the files backend is used for ref storage, by failing only the ones that are involved in the conflict while allowing others. * kn/refs-files-case-insensitive: refs/files: handle D/F conflicts during locking refs/files: handle F/D conflicts in case-insensitive FS refs/files: use correct error type when lock exists refs/files: catch conflicts on case-insensitive file-systems
2025-10-15Merge branch 'pw/rebase-i-cleanup-fix' into maint-2.51Junio C Hamano1-6/+22
"git rebase -i" failed to clean-up the commit log message when the command commits the final one in a chain of "fixup" commands, which has been corrected. * pw/rebase-i-cleanup-fix: sequencer: remove VERBATIM_MSG flag rebase -i: respect commit.cleanup when picking fixups
2025-10-15Merge branch 'jk/add-i-color' into maint-2.51Junio C Hamano2-0/+72
Some among "git add -p" and friends ignored color.diff and/or color.ui configuration variables, which is an old regression, which has been corrected. * jk/add-i-color: contrib/diff-highlight: mention interactive.diffFilter add-interactive: manually fall back color config to color.ui add-interactive: respect color.diff for diff coloring stash: pass --no-color to diff plumbing child processes
2025-10-15Merge branch 'sg/line-log-boundary-fixes' into maint-2.51Junio C Hamano7-0/+206
A corner case bug in "git log -L..." has been corrected. * sg/line-log-boundary-fixes: line-log: show all line ranges touched by the same diff range line-log: fix assertion error
2025-10-15Merge branch 'ps/upload-pack-oom-protection' into maint-2.51Junio C Hamano1-26/+42
A broken or malicious "git fetch" can say that it has the same object for many many times, and the upload-pack serving it can exhaust memory storing them redundantly, which has been corrected. * ps/upload-pack-oom-protection: upload-pack: don't ACK non-commits repeatedly in protocol v2 t5530: modernize tests
2025-10-15Merge branch 'ds/midx-write-fixes' into maint-2.51Junio C Hamano1-1/+21
Fixes multiple crashes around midx write-out codepaths. * ds/midx-write-fixes: midx-write: simplify error cases midx-write: reenable signed comparison errors midx-write: use uint32_t for preferred_pack_idx midx-write: use cleanup when incremental midx fails midx-write: put failing response value back midx-write: only load initialized packs
2025-10-15Merge branch 'ds/path-walk-repack-fix' into maint-2.51Junio C Hamano1-0/+63
"git repack --path-walk" lost objects in some corner cases, which has been corrected. cf. <CABPp-BHFxxGrqKc0m==TjQNjDGdO=H5Rf6EFsf2nfE1=TuraOQ@mail.gmail.com> * ds/path-walk-repack-fix: path-walk: create initializer for path lists path-walk: fix setup of pending objects
2025-10-15Merge branch 'ly/diff-name-only-with-diff-from-content' into maint-2.51Junio C Hamano2-6/+15
Various options to "git diff" that makes comparison ignore certain aspects of the differences (like "space changes are ignored", "differences in lines that match these regular expressions are ignored") did not work well with "--name-only" and friends. * ly/diff-name-only-with-diff-from-content: diff: ensure consistent diff behavior with ignore options
2025-10-15Merge branch 'jc/diff-no-index-in-subdir' into maint-2.51Junio C Hamano1-0/+17
"git diff --no-index" run inside a subdirectory under control of a Git repository operated at the top of the working tree and stripped the prefix from the output, and oddballs like "-" (stdin) did not work correctly because of it. Correct the set-up by undoing what the set-up sequence did to cwd and prefix. * jc/diff-no-index-in-subdir: diff: --no-index should ignore the worktree
2025-10-15Merge branch 'en/ort-rename-fixes' into maint-2.51Junio C Hamano1-15/+504
Various bugs about rename handling in "ort" merge strategy have been fixed. * en/ort-rename-fixes: merge-ort: fix directory rename on top of source of other rename/delete merge-ort: fix incorrect file handling merge-ort: clarify the interning of strings in opt->priv->path t6423: fix missed staging of file in testcases 12i,12j,12k t6423: document two bugs with rename-to-self testcases merge-ort: drop unnecessary temporary in check_for_directory_rename() merge-ort: update comments to modern testfile location
2025-10-15Merge branch 'dl/push-missing-object-error' into maint-2.51Junio C Hamano1-50/+4
"git push" had a code path that led to BUG() but it should have been a die(), as it is a response to a usual but invalid end-user action to attempt pushing an object that does not exist. cf. <xmqqo6spiyqp.fsf@gitster.g> * dl/push-missing-object-error: remote.c: convert if-else ladder to switch remote.c: remove BUG in show_push_unqualified_ref_name_error() t5516: remove surrounding empty lines in test bodies
2025-10-15Merge branch 'ps/reflog-migrate-fixes' into maint-2.51Junio C Hamano3-7/+142
"git refs migrate" to migrate the reflog entries from a refs backend to another had a handful of bugs squashed. * ps/reflog-migrate-fixes: refs: fix invalid old object IDs when migrating reflogs refs: stop unsetting REF_HAVE_OLD for log-only updates refs/files: detect race when generating reflog entry for HEAD refs: fix identity for migrated reflogs ident: fix type of string length parameter builtin/reflog: implement subcommand to write new entries refs: export `ref_transaction_update_reflog()` builtin/reflog: improve grouping of subcommands Documentation/git-reflog: convert to use synopsis type
2025-10-15Merge branch 'js/rebase-i-allow-drop-on-a-merge' into maint-2.51Junio C Hamano1-0/+1
During interactive rebase, using 'drop' on a merge commit lead to an error, which was incorrect. * js/rebase-i-allow-drop-on-a-merge: rebase -i: permit 'drop' of a merge commit
2025-10-15refs/files: deprecate writing symrefs as symbolic linksPatrick Steinhardt1-3/+23
The "files" backend has the ability to store symbolic refs as symbolic links, which can be configured via "core.preferSymlinkRefs". This feature stems back from the early days: the initial implementation of symbolic refs used symlinks exclusively. The symref format was only introduced in 9b143c6e15 (Teach update-ref about a symbolic ref stored in a textfile., 2005-09-25) and made the default in 9f0bb90d16 (core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02). This is all about 20 years ago, and there are no known reasons nowadays why one would want to use symlinks instead of symrefs. Mark the feature for deprecation in Git 3.0. Note that this only deprecates _writing_ symrefs as symbolic links. Reading such symrefs is still supported for now. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-14Merge branch 'jk/curl-global-trace-components' into maint-2.51Junio C Hamano1-1/+3
Adjust to the way newer versions of cURL selectivel enables tracing options, so that our tests can continue to work. * jk/curl-global-trace-components: curl: add support for curl_global_trace() components
2025-10-14Merge branch 'da/cargo-serialize' into maint-2.51Junio C Hamano1-10/+4
Makefile tried to run multiple "cargo build" which would not work very well; serialize their execution to work it around. * da/cargo-serialize: Makefile: build libgit-rs and libgit-sys serially
2025-10-14Merge branch 'jc/optional-path'Junio C Hamano1-10/+28
Configuration variables that take a pathname as a value (e.g. blame.ignorerevsfile) can be marked as optional by prefixing ":(optoinal)" before its value. * jc/optional-path: parseopt: values of pathname type can be prefixed with :(optional) config: values of pathname type can be prefixed with :(optional) t7500: fix GIT_EDITOR shell snippet t7500: make each piece more independent
2025-10-14Merge branch 'kh/format-patch-range-diff-notes'Junio C Hamano1-1/+15
"git format-patch --range-diff=... --notes=..." did not drive the underlying range-diff with correct --notes parameter, ending up comparing with different set of notes from its main patch output you would get from "git format-patch --notes=..." for a singleton patch. * kh/format-patch-range-diff-notes: format-patch: handle range-diff on notes correctly for single patches revision: add rdiff_log_arg to rev_info range-diff: rename other_arg to log_arg
2025-10-14Merge branch 'pw/add-p-hunk-splitting-fix'Junio C Hamano1-0/+31
Marking a hunk 'selected' in "git add -p" and then splitting made all the split pieces 'selected'; this has been changed to make them all 'undecided', which gives better end-user experience. * pw/add-p-hunk-splitting-fix: add-patch: update hunk splitability after editing add -p: mark split hunks as undecided
2025-10-13Merge branch 'kn/reftable-consistency-checks'Junio C Hamano3-4/+79
The reftable backend learned to sanity check its on-disk data more carefully. * kn/reftable-consistency-checks: refs/reftable: add fsck check for checking the table name reftable: add code to facilitate consistency checks fsck: order 'fsck_msg_type' alphabetically Documentation/fsck-msgids: remove duplicate msg id reftable: check for trailing newline in 'tables.list' refs: move consistency check msg to generic layer refs: remove unused headers
2025-10-13fast-import: add '--signed-tags=<mode>' optionChristian Couder2-0/+81
Recently, eaaddf5791 (fast-import: add '--signed-commits=<mode>' option, 2025-09-17) added support for controlling how signed commits are handled by `git fast-import`, but there is no option yet to decide about signed tags. To remediate that, let's add a '--signed-tags=<mode>' option to `git fast-import` too. With this, both `git fast-export` and `git fast-import` have both a '--signed-tags=<mode>' and a '--signed-commits=<mode>' supporting the same <mode>s. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-13fast-export: handle all kinds of tag signaturesChristian Couder1-0/+36
Currently the handle_tag() function in "builtin/fast-export.c" searches only for "\n-----BEGIN PGP SIGNATURE-----\n" in the tag message to find a tag signature. This doesn't handle all kinds of OpenPGP signatures as some can start with "-----BEGIN PGP MESSAGE-----" too, and this doesn't handle SSH and X.509 signatures either as they use "-----BEGIN SSH SIGNATURE-----" and "-----BEGIN SIGNED MESSAGE-----" respectively. To handle all these kinds of tag signatures supported by Git, let's use the parse_signed_buffer() function to properly find signatures in tag messages. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-13t9350: properly count annotated tagsChristian Couder1-4/+8
In "t9350-fast-export.sh", these existing tests: - 'fast-export | fast-import when main is tagged' - 'cope with tagger-less tags' are checking the number of annotated tags in the test repo by comparing it with some hardcoded values. This could be an issue if some new tests that have some prerequisites add new annotated tags to the repo before these existing tests. When the prerequisites would be satisfied, the number of annotated tags would be different from when some prerequisites would not be satisfied. As we are going to add new tests that add new annotated tags in a following commit, let's properly count the number of annotated tag in the repo by incrementing a counter each time a new annotated tag is added, and then by comparing the number of annotated tags to the value of the counter when checking the number of annotated tags. This is a bit ugly, but it makes it explicit that some tests are interdependent. Alternative solutions, like moving the new tests to the end of the script, were considered, but were rejected because they would instead hide the technical debt and could confuse developers in the future. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-13lib-gpg: allow tests with GPGSM or GPGSSH prereq firstChristian Couder1-4/+20
When the 'GPG' prereq is lazily tested, `mkdir "$GNUPGHOME"` could fail if the "$GNUPGHOME" directory already exists. This can happen if the 'GPGSM' or the 'GPGSSH' prereq has been lazily tested before as they already create "$GNUPGHOME". To allow the GPGSM or the GPGSSH prereq to appear before the GPG prereq in some test scripts, let's refactor the creation and setup of the "$GNUPGHOME"` directory in a new prepare_gnupghome() function that uses `mkdir -p "$GNUPGHOME"`. This will be useful in a following commit. Unfortunately the new prepare_gnupghome() function cannot be used when lazily testing the GPG2 prereq, because that would expose existing, hidden bugs in "t1016-compatObjectFormat.sh", so let's just document that with a NEEDSWORK comment. Helped-by: Todd Zullinger <tmz@pobox.com> Helped-by: Collin Funk <collin.funk1@gmail.com> Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-10t1016: make sure to use specified GPGJunio C Hamano1-1/+1
c348192a (t1016: clean up style, 2024-10-22) fixed a coding style violation that has an extra space between redirection operator ">" and the redirection target, but at the same time, replaced the use of "git config" to set a configuration variable to be used by the remainder of tests with "test_config". The pattern employed here is that the first set-up test prepares the environment to be used by subsequent tests, which then use the settings left by this set-up test to perform their tasks. Using test_config in the first set-up test means the config setting made by the set-up test is reverted at the end of the first set-up test, which totally misses the point. Go back to use "git config" to fix this. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-10Merge branch 'ps/gitlab-ci-windows-improvements'Junio C Hamano1-15/+19
GitLab CI improvements. * ps/gitlab-ci-windows-improvements: t8020: fix test failure due to indeterministic tag sorting gitlab-ci: upload Meson test logs as JUnit reports gitlab-ci: drop workaround for Python certificate store on Windows gitlab-ci: ignore failures to disable realtime monitoring gitlab-ci: dedup instructions to disable realtime monitoring
2025-10-09t/lib-gpg: call prepare_gnupghome() in GPG2 prereqTodd Zullinger1-0/+1
The GPG2 prereq added in 2f36339fa8 (t/lib-gpg: introduce new prereq GPG2, 2023-06-04) does not create the $GNUPGHOME directory. Tests which use the GPG2 prereq without previously using the GPG prereq fail because of the missing directory. This currently affects t1016-compatObjectFormat. Ensure $GNUPGHOME is created in the GPG2 prereq. Signed-off-by: Todd Zullinger <tmz@pobox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-09t/lib-gpg: add prepare_gnupghome() to create GNUPGHOME dirTodd Zullinger1-4/+7
We create the $GNUPGHOME directory in both the GPG and GPGSSH prereqs. Replace the redundancy with a function. Use `mkdir -p` to ensure we do not fail if a test includes more than one of these prereqs. Signed-off-by: Todd Zullinger <tmz@pobox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-09t1010: use BROKEN_OBJECTS prerequisitebrian m. carlson1-5/+8
When hash compatibility mode is enabled, we cannot write broken objects because they cannot be mapped into the other hash algorithm. Use the BROKEN_OBJECTS prerequisite to disable these tests and the writing of broken objects in this mode. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-09t: allow specifying compatibility hashbrian m. carlson2-2/+20
We want to specify a compatibility hash for testing interactions for SHA-256 repositories where we have SHA-1 compatibility enabled. Allow the user to specify this scenario in the test suite by setting GIT_TEST_DEFAULT_HASH to "sha256:sha1". Note that this will get passed into GIT_DEFAULT_HASH, which Git itself does not presently support. However, we will support this in a future commit. Since we'll now want to know the value for a specific version, let's add the ability to specify either the storage hash (in this case, SHA-256) or the compatibility hash (SHA-1). We use a different value for the compatibility hash that will be enabled for all repositories (test_repo_compat_hash_algo) versus the one that is used individually in some tests (test_compat_hash_algo), since we want to still run those individual tests without requiring that the testsuite be run fully in a compatibility mode. In some cases, we'll need to adjust our test suite to work in a proper way with a compatibility hash. For example, in such a case, we'll only use pack index v3, since v1 and v2 lack support for multiple algorithms. Since we won't want to write those older formats, we'll need to skip tests that do so. Let's add a COMPAT_HASH prerequisite for this purpose. Finally, in this scenario, we can no longer rely on having broken objects work since we lack compatibility mappings to rewrite objects in the repository. Add a prerequisite, BROKEN_OBJECTS, that we define in terms of COMPAT_HASH and checks to see if creating deliberately broken objects is possible, so that we can disable these tests if not. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-09fsck: consider gpgsig headers expected in tagsbrian m. carlson1-0/+54
When we're creating a tag, we want to make sure that gpgsig and gpgsig-sha256 headers are allowed for the commit. The default fsck behavior is to ignore the fact that they're left over, but some of our tests enable strict checking which flags them nonetheless. Add improved checking for these headers as well as documentation and several tests. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-09rev-parse: allow printing compatibility hashbrian m. carlson1-0/+34
Right now, we have a way to print the storage hash, the input hash, and the output hash, but we lack a way to print the compatibility hash. Add a new type to --show-object-format, compat, which prints this value. If no compatibility hash exists, simply print a newline. This is important to allow users to use multiple options at once while still getting unambiguous output. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-08Merge branch 'mh/doc-credential-url-prefix'Junio C Hamano1-4/+15
Doc update to describe a feature that has already been implemented. * mh/doc-credential-url-prefix: docs/gitcredentials: describe URL prefix matching
2025-10-08Merge branch 'kn/ref-cache-seek-fix'Junio C Hamano1-0/+65
Handling of an empty subdirectory of .git/refs/ in the ref-files backend has been corrected. * kn/ref-cache-seek-fix: refs/ref-cache: fix SEGFAULT when seeking in empty directories
2025-10-08Merge branch 'ml/reflog-write-committer-info-fix'Junio C Hamano1-0/+36
"git reflog write" did not honor the configured user.name/email which has been corrected. * ml/reflog-write-committer-info-fix: builtin/reflog: respect user config in "write" subcommand
2025-10-07Merge branch 'ps/odb-clean-stale-wrappers'Junio C Hamano1-6/+4
Code clean-up. * ps/odb-clean-stale-wrappers: odb: drop deprecated wrapper functions
2025-10-07Merge branch 'ps/packfile-store'Junio C Hamano2-2/+2
Code clean-up around the in-core list of all the pack files and object database(s). * ps/packfile-store: packfile: refactor `get_packed_git_mru()` to work on packfile store packfile: refactor `get_all_packs()` to work on packfile store packfile: refactor `get_packed_git()` to work on packfile store packfile: move `get_multi_pack_index()` into "midx.c" packfile: introduce function to load and add packfiles packfile: refactor `install_packed_git()` to work on packfile store packfile: split up responsibilities of `reprepare_packed_git()` packfile: refactor `prepare_packed_git()` to work on packfile store packfile: reorder functions to avoid function declaration odb: move kept cache into `struct packfile_store` odb: move MRU list of packfiles into `struct packfile_store` odb: move packfile map into `struct packfile_store` odb: move initialization bit into `struct packfile_store` odb: move list of packfiles into `struct packfile_store` packfile: introduce a new `struct packfile_store`
2025-10-07parseopt: values of pathname type can be prefixed with :(optional)Junio C Hamano1-0/+10
In the previous step, we introduced an optional filename that can be given to a configuration variable, and nullify the fact that such a configuration setting even existed if the named path is missing or empty. Let's do the same for command line options that name a pathname. Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-07config: values of pathname type can be prefixed with :(optional)Junio C Hamano1-0/+8
Sometimes people want to specify additional configuration data as "best effort" basis. Maybe commit.template configuration file points at somewhere in ~/template/ but on a particular system, the file may not exist and the user may be OK without using the template in such a case. When the value given to a configuration variable whose type is pathname wants to signal such an optional file, it can be marked by prepending ":(optional)" in front of it. Such a setting that is marked optional would avoid getting the command barf for a missing file, as an optional configuration setting that names a missing file is not even seen. cf. <xmqq5ywehb69.fsf@gitster.g> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-07t7500: fix GIT_EDITOR shell snippetJunio C Hamano1-2/+2
2140b140 (commit: error out for missing commit message template, 2011-02-25) defined GIT_EDITOR="echo hello >\"\$1\"" for these two tests, with the intention that 'hello' would be written in the given file, but as Phillip Wood points out, GIT_EDITOR is invoked by shell after getting expanded to sh -c 'echo hello >"$1" "$@"' 'echo hello >"$1"' path/to/file which is not what we want. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-07refs/reftable: add fsck check for checking the table nameKarthik Nayak2-0/+59
Add glue code in 'refs/reftable-backend.c' which calls the reftable library to perform the fsck checks. Here we also map the reftable errors to Git' fsck errors. Introduce a check to validate table names for a given reftable stack. Also add 'badReftableTableName' as a corresponding error within Git. The reftable specification mentions: It suggested to use ${min_update_index}-${max_update_index}-${random}.ref as a naming convention. So treat non-conformant file names as warnings. While adding the fsck header to 'refs/reftable-backend.c', modify the list to maintain lexicographical ordering. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-07reftable: check for trailing newline in 'tables.list'Karthik Nayak1-4/+20
In the reftable format, the 'tables.list' file contains a newline separated list of tables. While we parse this file, we do not check or care about the last newline. Tighten the parser in `parse_names()` to return an appropriate error if the last newline is missing. This requires modification to `parse_names()` to now return the error while accepting the output as a third argument. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-06add-patch: reset "permitted" at loop startRené Scharfe1-0/+14
Don't accumulate allowed options from any visited hunks, start fresh at the top of the loop instead and only record the allowed options for the current hunk. Reported-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-06add-patch: let options a and d roll over like y and nRené Scharfe1-6/+6
Options a and d stage and unstage all undecided hunks towards the bottom of the array of hunks, respectively, and then roll over to the very first hunk. The first part is similar to y and n if the current hunk is the last one in the array, but they roll over to the next undecided hunk if there is any. That's more useful; do it for a and d as well. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-06add-patch: let options k and K roll over like j and JRené Scharfe1-20/+20
Options j and J roll over at the bottom and go to the first undecided hunk and hunk 1, respectively. Let options k and K do the same when they reach the top of the hunk array, so let them go to the last undecided hunk and the last hunk, respectively, for consistency. Also use the same direction-neutral error messages. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-06add-patch: let options y, n, j, and e roll over to next undecidedRené Scharfe1-0/+22
The options y, n, and e mark the current hunk as decided. If there's another undecided hunk towards the bottom of the hunk array they go there. If there isn't, but there is another undecided hunk towards the top then they go to the very first hunk, no matter if it has already been decided on. The option j does basically the same move. Technically it is not allowed if there's no undecided hunk towards the bottom, but the variable "permitted" is never reset, so this permission is retained from the very first hunk. That may a bug, but this behavior is at least consistent with y, n, and e and arguably more useful than refusing to move. Improve the roll-over behavior of these four options by moving to the first undecided hunk instead of hunk 1, consistent with what they do when not rolling over. Also adjust the error message for j, as it will only be shown if there's no other undecided hunk in either direction. Reported-by: Windl, Ulrich <u.windl@ukr.de> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-06add-patch: document that option J rolls overRené Scharfe1-4/+14
The variable "permitted" is not reset after moving to a different hunk, so it only accumulates permission and doesn't necessarily reflect those of the current hunk. This may be a bug, but is actually useful with the option J, which can be used at the last hunk to roll over to the first hunk. Make this particular behavior official. Also adjust the error message, as it will only be shown if there's just a single hunk. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-02Merge branch 'kh/you-still-use-whatchanged-fix'Junio C Hamano1-0/+57
The "do you still use it?" message given by a command that is deeply deprecated and allow us to suggest alternatives has been updated. * kh/you-still-use-whatchanged-fix: BreakingChanges: remove claim about whatchanged reports whatchanged: remove not-even-shorter clause whatchanged: hint about git-log(1) and aliasing you-still-use-that??: help the user help themselves t0014: test shadowing of aliases for a sample of builtins git: allow alias-shadowing deprecated builtins git: move seen-alias bookkeeping into handle_alias(...) git: add `deprecated` category to --list-cmds Makefile: don’t add whatchanged after it has been removed
2025-10-02Merge branch 'ps/config-get-color-fixes'Junio C Hamano1-177/+172
The use of "git config get" command to learn how ANSI color sequence is for a particular type, e.g., "git config get --type=color --default=reset no.such.thing", isn't very ergonomic. * ps/config-get-color-fixes: builtin/config: do not spawn pager when printing color codes builtin/config: special-case retrieving colors without a key builtin/config: do not die in `get_color()` t1300: small style fixups t1300: write test expectations in the test's body
2025-10-02Merge branch 'cc/fast-import-strip-signed-commits'Junio C Hamano2-0/+107
"git fast-import" learned that "--signed-commits=<how>" option that corresponds to that of "git fast-export". * cc/fast-import-strip-signed-commits: fast-import: add '--signed-commits=<mode>' option gpg-interface: refactor 'enum sign_mode' parsing
2025-10-02Merge branch 'ms/refs-optimize'Junio C Hamano4-429/+450
"git refs optimize" is added for not very well explained reason despite it does the same thing as "git pack-refs"... * ms/refs-optimize: t: add test for git refs optimize subcommand t0601: refactor tests to be shareable builtin/refs: add optimize subcommand doc: pack-refs: factor out common options builtin/pack-refs: factor out core logic into a shared library builtin/pack-refs: convert to use the generic refs_optimize() API reftable-backend: implement 'optimize' action files-backend: implement 'optimize' action refs: add a generic 'optimize' API
2025-10-02t8020: fix test failure due to indeterministic tag sortingPatrick Steinhardt1-15/+19
In e6c06e87a2 (last-modified: fix bug when some paths remain unhandled, 2025-09-18), we have fixed a bug where under certain circumstances, git-last-modified(1) would BUG because there's still some unhandled paths. The fix claims that the root cause here is criss-cross merges, and it adds a test case that seemingly exercises this. Curiously, this test case fails on some systems because the actual output does not match our expectations: diff --git a/expect b/actual index 5271607..bdc620e 100644 --- a/expect --- b/actual @@ -1,3 +1,3 @@ km3 a -k2 k +km2 k 1 file error: last command exited with $?=1 not ok 15 - last-modified with subdir and criss-cross merge The output we see is git-name-rev(1) with `--annotate-stdin`. What it does is to take the output of git-last-modified(1), which contains object IDs of the blamed commits, and convert those object IDs into the names of the corresponding tags. Interestingly, we indeed have both "k2" and "km2" as tags, and even more interestingly both of these tags point to the same commit. So the output we get isn't _wrong_, as the tags are ambiguous. But why do both of these tags point to the same commit? "km2" really is supposed to be a merge, but due to the way the test is constructed the merge turns into a fast-forward merge. Which means that the resulting commit-graph does not even contain a criss-cross merge in the first place! A quick test though shows that the test indeed triggers the bug, so the initial analysis that the behaviour is triggered by such merges must be wrong. And it is: seemingly, the issue isn't with criss-cross merges, but rather with a graph where different files in the same directory were modified on both sides of a merge. Refactor the test so that we explicitly test for this specific situation instead of mentioning the "criss-cross merge" red herring. As the test is very specific to the actual layout of the repository we also adapt it to use its own standalone repository. Note that this requires us to drop the `test_when_finished` call in `check_last_modified` because it's not supported to execute that function in a subshell. This refactoring also fixes the original tag ambiguity that caused us to fail on some platforms. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-01docs/gitcredentials: describe URL prefix matchingM Hickford1-4/+15
Documentation was inaccurate since 9a121b0d226 (credential: handle `credential.<partial-URL>.<key>` again, 2020-04-24) Add tests for documented behaviour. Signed-off-by: M Hickford <mirth.hickford@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-01refs/ref-cache: fix SEGFAULT when seeking in empty directoriesKarthik Nayak1-0/+65
The 'cache_ref_iterator_seek()' function is used to seek the `ref_iterator` to the desired reference in the ref-cache mechanism. We use the seeking functionality to implement the '--start-after' flag in 'git-for-each-ref(1)'. When using the files-backend with packed-refs, it is possible that some of the refs directories are empty. For e.g. just after repacking, the 'refs/heads' directory would be empty. The ref-cache seek mechanism, doesn't take this into consideration when descending into a subdirectory, and makes an out of bounds access, causing SEGFAULT as we try to access entries within the directory. Fix this by breaking out of the loop when we enter an empty directory. Since we start with the base directory of 'refs/' which is never empty, it is okay to perform this check after the first iteration in the `do..while` clause. Add tests which simulate this behavior and also provide coverage over using the feature over packed-refs. Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-01builtin/reflog: respect user config in "write" subcommandMichael Lohmann1-0/+36
The reflog write recognizes only GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL environment variables, but forgot to honor the user.name and user.email configuration variables, due to lack of repo_config() call to grab these values from the configuration files. The test suite sets these variables, so this behavior was unnoticed. Ensure that the reflog write also uses the values of user.name and user.email if set in the Git configuration. Co-authored-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Michael Lohmann <git@lohmann.sh> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-29Merge branch 'tc/last-modified-recursive-fix'Junio C Hamano1-0/+16
"git last-modified" operating in non-recursive mode used to trigger a BUG(), which has been corrected. * tc/last-modified-recursive-fix: last-modified: fix bug when some paths remain unhandled
2025-09-29Merge branch 'kn/refs-files-case-insensitive'Junio C Hamano2-1/+166
Deal more gracefully with directory / file conflicts when the files backend is used for ref storage, by failing only the ones that are involved in the conflict while allowing others. * kn/refs-files-case-insensitive: refs/files: handle D/F conflicts during locking refs/files: handle F/D conflicts in case-insensitive FS refs/files: use correct error type when lock exists refs/files: catch conflicts on case-insensitive file-systems
2025-09-29Merge branch 'dk/stash-apply-index'Junio C Hamano2-1/+40
The stash.index configuration variable can be set to make "git stash pop/apply" pretend that it was invoked with "--index". * dk/stash-apply-index: stash: honor stash.index in apply, pop modes stash: refactor private config globals t3905: remove unneeded blank line t3903: reduce dependencies on previous tests
2025-09-29Merge branch 'jk/setup-revisions-freefix'Junio C Hamano1-0/+9
There are double frees and leaks around setup_revisions() API used in "git stash show", which has been fixed, and setup_revisions() API gained a wrapper to make it more ergonomic when using it with strvec-manged argc/argv pairs. * jk/setup-revisions-freefix: revision: retain argv NULL invariant in setup_revisions() treewide: pass strvecs around for setup_revisions_from_strvec() treewide: use setup_revisions_from_strvec() when we have a strvec revision: add wrapper to setup_revisions() from a strvec revision: manage memory ownership of argv in setup_revisions() stash: tell setup_revisions() to free our allocated strings
2025-09-29Merge branch 'pw/rebase-i-cleanup-fix'Junio C Hamano1-6/+22
"git rebase -i" failed to clean-up the commit log message when the command commits the final one in a chain of "fixup" commands, which has been corrected. * pw/rebase-i-cleanup-fix: sequencer: remove VERBATIM_MSG flag rebase -i: respect commit.cleanup when picking fixups
2025-09-29Merge branch 'jc/3.0-default-initial-branch-to-main-addendum'Junio C Hamano2-4/+8
Keep giving hint about the default initial branch name for users who may be surprised after Git 3.0 switch-over. * jc/3.0-default-initial-branch-to-main-addendum: initial branch: give hints after switching the default name
2025-09-29Merge branch 'pw/3.0-default-initial-branch-to-main'Junio C Hamano101-232/+253
Declare that "git init" that is not otherwise configured uses 'main' as the initial branch, not 'master', starting Git 3.0. * pw/3.0-default-initial-branch-to-main: t0613: stop setting default initial branch t9902: switch default branch name to main t4013: switch default branch name to main breaking-changes: switch default branch to main
2025-09-29Merge branch 'ps/clar-updates'Junio C Hamano34-258/+1415
Import a newer version of the clar unit testing framework. * ps/clar-updates: t/unit-tests: update to 10e96bc t/unit-tests: update clar to fcbed04
2025-09-29Merge branch 'ps/packfile-store' into tb/incremental-midx-part-3.1Junio C Hamano2-2/+2
* ps/packfile-store: packfile: refactor `get_packed_git_mru()` to work on packfile store packfile: refactor `get_all_packs()` to work on packfile store packfile: refactor `get_packed_git()` to work on packfile store packfile: move `get_multi_pack_index()` into "midx.c" packfile: introduce function to load and add packfiles packfile: refactor `install_packed_git()` to work on packfile store packfile: split up responsibilities of `reprepare_packed_git()` packfile: refactor `prepare_packed_git()` to work on packfile store packfile: reorder functions to avoid function declaration odb: move kept cache into `struct packfile_store` odb: move MRU list of packfiles into `struct packfile_store` odb: move packfile map into `struct packfile_store` odb: move initialization bit into `struct packfile_store` odb: move list of packfiles into `struct packfile_store` packfile: introduce a new `struct packfile_store`
2025-09-28t7500: make each piece more independentJunio C Hamano1-8/+8
These tests prepare the working tree & index state to have something to be committed, and try a sequence of "test_must_fail git commit". If an earlier one did not fail by a bug, a later one will fail for a wrong reason (namely, "nothing to commit"). Give them "--allow-empty" to make sure that they would work even when there is nothing to commit by accident. Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-25diff --no-index: fix logic for paths ending in '/'Jacob Keller1-0/+16
If one of the two provided paths for git diff --no-index ends in a '/', a failure similar to the following occurs: $ git diff --no-index -- /tmp/ /tmp/ ':!' fatal: `pos + len' is too far after the end of the buffer This occurs because of an incorrect calculation of the skip lengths in diff_no_index(). The code wants to calculate the length of the string, but add one in case the string doesn't end with a slash. The method it uses is incorrect, as it always checks the trailing NUL character of the string. This will never be a '/', so we always add one. In the event that we *do* have a trailing slash, this will create an off-by-one length error later when using the skip value. The most straightforward fix would be to correct the skip1 and skip2 lengths by using ends_with(). However, Johannes made a good point that the existing logic is wasting a lot of computation. We generate the match string by copying the path in and then skipping almost all of it immediately with a potentially expensive memmove() from the strbuf_remove() call. We also re-initialize the match stringbuf each time we call read_directory_contents. The read_directory_contents really wants a path that is rooted at the start of the directory scan. We're currently building this by taking the full path and stripping out the start portion. Instead, replace this logic by building up the portion of the match as we go. Start by initializing two strbuf in diff_no_index containing the empty string. Pass these into queue_diff, which in turn passes the appropriate left or right side into read_directory_contents. As before, we build up the matches by appending elements to the match path and then clearing them using strbuf_setlen. In the recursive portion of the queue_diff algorithm, we build up new match paths the same way that we build up new buffer paths, by appending the elements and then clearing them with strbuf_setlen after each iteration. This is cheaper as it avoids repeated allocations, and is a bit simpler to track what is going on. Add a couple of test cases that pass in paths already ending in '/', to ensure the tests cover this regression. Reported-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Closes: https://lore.kernel.org/git/c75ec5f9-407a-6555-d4fb-bb629d54ec61@gmx.de/ Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> [jc: small leakfixes at the end of diff_no_index()] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-25format-patch: handle range-diff on notes correctly for single patchesKristoffer Haugsbakk1-1/+15
(The two next paragraphs are taken from the previous commit.) git-format-patch(1) supports Git notes by showing them beneath the patch/commit message, similar to git-log(1). The command also supports showing those same notes ref names in the range diff output. Note *the same* ref names; any Git notes options or configuration variables need to be handed off to the range-diff machinery. This works correctly in the case when the range diff is on the cover letter. But it does not work correctly when the output is a single patch with an embedded range diff. Concretely, git-format-patch(1) needs to pass `--[no-]notes` options on to the range-diff subprocess in `range-diff.c`. Range diffs for single- commit series are handled in `log-tree.c`. But `log-tree.c` had no access to any `log_arg` variable before we added it to `rev_info` in the previous commit. Use that new struct member to fix this inconsistency. Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-25add-patch: update hunk splitability after editingPhillip Wood1-0/+21
If, when the user edits a hunk, they change deletion lines into context lines or vice versa, then the number of hunks that the edited hunk can be split into may differ from the unedited hunk. This means that so we should recalculate `hunk->splittable_into` after the hunk has been edited. In practice users are unlikely to hit this bug as it is doubtful that a user who has edited a hunk will split it afterwards. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-25add -p: mark split hunks as undecidedPhillip Wood1-0/+10
When a hunk is split, each of the new hunks inherits whether it is selected or not from the original hunk. If a selected hunk is split all of the new hunks are marked as "selected" and the user is only prompted with the first of the split hunks. The user is not asked whether or not they wish to select the rest of the new hunks. This means that if they wish to deselect any of the new hunks apart from the first one they have to navigate back to the hunk they want to deselect before they can deselect it. This is unfortunate as the user is presumably splitting the original hunk because they only want to select some sub-set of it. Instead mark all the new hunks as "undecided" so that the user is prompted whether they wish to select each one in turn. In the case where the user only wants to change the selection of the first of the split hunks they will now have to do more work re-selecting the remaining split hunks. However, changing the selection of any of the other newly created hunks is now much simpler as the user no-longer has to navigate back to them in order to change their selected state. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-24packfile: refactor `get_all_packs()` to work on packfile storePatrick Steinhardt2-2/+2
The `get_all_packs()` function prepares the packfile store and then returns its packfiles. Refactor it to accept a packfile store instead of a repository to clarify its scope. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-23Merge branch 'jk/add-i-color'Junio C Hamano2-0/+72
Some among "git add -p" and friends ignored color.diff and/or color.ui configuration variables, which is an old regression, which has been corrected. * jk/add-i-color: contrib/diff-highlight: mention interactive.diffFilter add-interactive: manually fall back color config to color.ui add-interactive: respect color.diff for diff coloring stash: pass --no-color to diff plumbing child processes
2025-09-23Merge branch 'cc/promisor-remote-capability'Junio C Hamano1-0/+65
The "promisor-remote" capability mechanism has been updated to allow the "partialCloneFilter" settings and the "token" value to be communicated from the server side. * cc/promisor-remote-capability: promisor-remote: use string_list_split() in mark_remotes_as_accepted() promisor-remote: allow a client to check fields promisor-remote: use string_list_split() in filter_promisor_remote() promisor-remote: refactor how we parse advertised fields promisor-remote: use string constants for 'name' and 'url' too promisor-remote: allow a server to advertise more fields promisor-remote: refactor to get rid of 'struct strvec'
2025-09-22revision: manage memory ownership of argv in setup_revisions()Jeff King1-0/+5
The setup_revisions() function takes an argc/argv pair and consumes arguments from it, returning a reduced argc count to the caller. But it may also overwrite entries within the argv array, as it shifts unknown options to the front of argv (so they can be found in the range of 0..argc-1 after we return). For a normal argc/argv coming from the operating system, this is OK. We don't need to worry about memory ownership of the strings in those entries. But some callers pass in allocated strings from a strvec, and we do need to care about those. We faced a similar issue in f92dbdbc6a (revisions API: don't leak memory on argv elements that need free()-ing, 2022-08-02), which added an option for callers to tell us that elements need to be freed. But the implementation within setup_revisions() was incomplete. It only covered the case of dropping "--", but not the movement of unknown options. When we shift argv entries around, we should free the elements we are about to overwrite, so they are not leaked. For example, in: git stash show -p --invalid we will pass this to setup_revisions(): argc = 3, argv[] = { "show", "-p", "--invalid", NULL } which will then return: argc = 2, argv[] = { "show", "--invalid", "--invalid", NULL } overwriting the "-p" entry, which is leaked unless we free it at that moment. You can see in the output above another potential problem. We now have two copies of the "--invalid" string. If the caller does not respect the new argc when free-ing the strings via strvec_clear(), we'll get a double-free. And git-stash suffers from this, and will crash with the above command. So it seems at first glance that the solution is to just assign the reduced argc to the strvec.nr field in the caller. Then it would stop after freeing only any copied entries. But that's not always right either! Remember that we are reducing "argc" to account for elements we've consumed. So if there isn't an invalid option, we'd turn: argc = 2, argv[] = { "show", "-p", NULL } into: argc = 1, argv[] = { "show", "-p", NULL } In that case strvec_clear() must keep looking past the shortened argc we return to find the original "-p" to free. It needs to use the original argc to do that. We can solve this by turning our argv writes into strict moves, not copies. When we shuffle an unknown option to the front, we'll overwrite its old position with NULL. That leaves an argv array that may have NULL "holes" in it. So in the "--invalid" example above we get: argc = 2, argv[] = { "show", "--invalid", NULL, NULL } but something like "git stash -p --invalid -p" would yield: argc = 3, argv[] = { "show", "--invalid", NULL, "-p", NULL } because we move "--invalid" to overwrite the first "-p", but the second one is quietly consumed. But strvec_clear() can handle that fine (it iterates over the "nr" field, and passing NULL to free() is OK). To ease the implementation, I've introduced a helper function. It's a little hacky because it must take a double-pointer to set the old position to NULL. Which in turn means we cannot pass "&arg", our local alias for the current entry we're parsing, but instead "&argv[i]", the pointer in the original array. And to make it even more confusing, we delegate some of this work to handle_revision_opt(), which is passed a subset of the argv array, so is always working on "&argv[0]". Likewise, because handle_revision_opt() only receives the part of argv left to parse, it receives the array to accumulate unknown options as a separate unkc/unkv pair. But we're always working on the same argv array, so our strategy works fine. I suspect this would be a bit more obvious (and avoid some pointer cleverness) if all functions saw the full argv array and worked with positions within it (and our new helper would take two positions, a src and dst). But that would involve refactoring handle_revision_opt(). I punted on that, as what's here is not too ugly and is all contained within revision.c itself. The new test demonstrates that "git stash show -p --invalid" no longer crashes with a double-free (because we move instead of copy). And it passes with SANITIZE=leak because we free "-p" before overwriting. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22stash: tell setup_revisions() to free our allocated stringsJeff King1-0/+4
In "git stash show", we do a first pass of parsing our command line options by splitting them into revision args and stash args. These are stored in strvecs, and we pass the revision args to setup_revisions(). But setup_revisions() may modify the argv we pass it, causing us to leak some of the entries. In particular, if it sees a "--" string, that will be dropped from argv. This is the same as other cases addressed by f92dbdbc6a (revisions API: don't leak memory on argv elements that need free()-ing, 2022-08-02), and we should fix it the same way: by passing the free_removed_argv_elements option to setup_revisions(). The added test here is run only with SANITIZE=leak, without checking its output, because the behavior of stash with "--" is a little odd: 1. Running "git stash show" will show --stat output. But running "git stash show --" will show --patch. 2. I'd expect a non-option after "--" to be treated as a pathspec, so: git stash show -p 1 -- foo would look treat "1" as a stash (a synonym for stash@{1}) and restrict the resulting diff to "foo". But it doesn't. We split the revision/stash args without any regard to "--". So in the example above both "1" and "foo" are stashes. Which is an error, but also: git stash show -- foo treats "foo" as a stash, not a pathspec. These are both oddities that we may want to address (or may not, if we want to retain historical quirks). But they are well outside the scope of this patch. So for now we'll just let the tests confirm we aren't leaking without otherwise expecting any behavior. If we later address either of those points and end up with another test that covers "stash show --", we can drop this leak-only test. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22t/unit-tests: update to 10e96bcPatrick Steinhardt24-236/+320
Update to 10e96bc (Merge pull request #127 from pks-gitlab/pks-ci-improvements, 2025-09-22). This commit includes a couple of changes: - The GitHub CI has been updated to include a 32 bit CI job. Furthermore, the jobs now compile with "-Werror" and more warnings enabled. - An issue was addressed where `uintptr_t` is not available on NonStop [1]. - The clar selftests have been restructured so that it is now possible to add small test suites more readily. This was done to add tests for the above addressed issue, where we now use "%p" to print pointers in a platform dependent way. - An issue was addressed where the test output had a trailing whitespace with certain output formats, which caused whitespace issues in the test expectation files. [1]: <01c101dc2842$38903640$a9b0a2c0$@nexbridge.com> Reported-by: Randall S. Becker <rsbecker@nexbridge.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22builtin/config: do not spawn pager when printing color codesPatrick Steinhardt1-0/+9
With `git config get --type=color` the user asks us to parse a specific configuration key and turn the value into an ANSI color escape sequence. The printed string can then for example be used as part of shell scripts to reuse the same colors as Git. Right now though we set up the auto-pager, which means that the string may be written to the pager instead of directly to the terminal. This behaviour is problematic for two reasons: - Color codes are meant for direct terminal output; writing them into a pager does not seem like a sensible thing to do without additional text. - It is inconsistent with `git config --get-color`, which never uses a pager, despite the fact that we claim `git config get --type=color` to be a drop-in replacement in git-config(1). Fix this by disabling the pager when outputting color sequences. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22builtin/config: special-case retrieving colors without a keyPatrick Steinhardt1-0/+11
Our documentation for git-config(1) has a section where it explains how to parse and use colors as Git would configure them. In order to get the ANSI color escape sequence to reset the colors to normal we recommend the following command: $ git config get --type=color --default="reset" "" This command is not supposed to parse any configuration keys. Instead, it is expected to parse the "reset" default value and turn it into a proper ANSI color escape sequence. It was reported though [1] that this command doesn't work: $ git config get --type=color --default="reset" "" error: key does not contain a section: This error was introduced in 4e51389000 (builtin/config: introduce "get" subcommand, 2024-05-06), where we introduced the "get" subcommand to retrieve configuration values. The preimage of that commit used `git config --get-color "" "reset"` instead, which still works. This use case is really quite specific to parsing colors, as it wouldn't make sense to give git-config(1) a default value and an empty config key only to return that default value unmodified. But with `--type=color` we don't return the value directly; we instead parse the value into an ANSI escape sequence. As such, we can easily special-case this one use case: - If the provided config key is empty; - the user is asking for a color code; and - the user has provided a default value, then we call `get_color()` directly. Do so to make the documented command work as expected. [1]: <aI+oQvQgnNtC6DVw@szeder.dev> Reported-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22t1300: small style fixupsPatrick Steinhardt1-14/+24
We have a couple of small style violations in t1300: - An empty newline at the start of the test body. - The test command is sometimes on the same line as the test name. - The closing single-quote is sometimes on the same line as the last command of the test. Fix these. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22t1300: write test expectations in the test's bodyPatrick Steinhardt1-163/+128
There are a bunch of tests in t1300 where we write the test expectation handed over to `test_cmp ()` outside of the test body. This does not match our modern test style, and there isn't really a reason why this would need to happen outside of the test bodies. Convert those to instead do so as part of the test itself. While at it, normalize these tests to use `<<\EOF` for those that don't use variable expansion and `<<-EOF` for those that aren't sensitive to indentation. Note that there are two exceptions that we leave as-is for now since they are reused across tests. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-21stash: honor stash.index in apply, pop modesD. Ben Knoble1-0/+37
With stash.index=true, git-stash(1) command now tries to reinstate the index by default in the "apply" and "pop" modes. Not doing so creates a common trap [1], [2]: "git stash apply" is not the reverse of "git stash push" because carefully staged indices are lost and have to be manually recreated. OTOH, this mode is not always desirable and may create more conflicts when applying stashes. As usual, "--no-index" will disable this behavior if you set "stash.index". [1]: https://lore.kernel.org/git/CAPx1GvcxyDDQmCssMjEnt6JoV6qPc5ZUpgPLX3mpUC_4PNYA1w@mail.gmail.com/ [2]: https://lore.kernel.org/git/c5a811ac-8cd3-c389-ac6d-29020a648c87@gmail.com/ Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-21t3905: remove unneeded blank lineD. Ben Knoble1-1/+0
This is leftover from 787513027a (stash: Add --include-untracked option to stash and remove all untracked files, 2011-06-24) when it was converted in bbaa45c3aa (t3905: move all commands into test cases, 2021-02-08). Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-21t3903: reduce dependencies on previous testsD. Ben Knoble1-0/+3
Skipping previous tests to work through only failing tests with arguments like --run=4,122- causes some tests to fail because subdir doesn't exist yet (it is created by a previous test; typically "unstashing in a subdirectory"). Create it on demand for tests that need it, but don't fail (-p) if the directory already exists. Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>